AndrasCsanyi
AndrasCsanyi

Reputation: 4245

How is possible to get the bindings value in component controller with Angular 1.5 and Typescript?

I would like to create a left hand menu component which displays different menu structure depending on the string it gets via binding.

For example:

<left-hand-menu-component module='abc'></left-hand-menu-component>

Then it shows only the abc module's menu structure. In order to achieve that the component controller must be able to work with the data comes trough bindings and make the necessary service calls.

I have been googling around for a while how to achieve this and I have find this and this posts and this posts. The example available at Angular documentation is too simple.

I have put together the example's code above and that part is missing when the controller can work with the value coming trough bindings.

It is even possible? Or it is rather a directive than a component?

Do you know example where it is displayed, blog entry or any source?

The two console.log in the controller constructor write out 'undefined' as result.

Component:

module qa.gonogo {
    "use strict";

    export class LeftHandMenuComponent implements ng.IComponentOptions {


        public transclude: boolean = false;
        public controller: Function = LeftHandMenuComponentController;
        public controllerAs: string = "vm";
        public templateUrl: string = "app/content/lefthandmenu/leftHandMenuComponentTemplate.html";
        public bindings: any;

        constructor() {
            this.bindings = {
                module: '<'
            }
        }
    }

    angular
        .module("goNoGo")
        .component("gonogoLefthandmenuComponent", new LeftHandMenuComponent());

}

Controller:

export class LeftHandMenuComponentController implements ILeftHandMenuComponentController {

        menuStructure: IMenuStructure[];
        closeOthers: boolean = true;

        static $inject = [];

        constructor(public module: string) {
            console.log('binding', module);
            console.log('binding2', this.module);
        }

        public $onInit = (): void => {
            this.populateMenuStructure();
        }

Route.

$stateProvider
            .state("bfts",
                <ng.ui.IState>{
                    url: "/bfts",
                    views: <any>{
                        "leftHandMenu": <ng.ui.IState>{
                            template: "<gonogo-lefthandmenu-component module='bfts'></gonogo-lefthandmenu-component>"
                        },
                        "content": <ng.ui.IState>{
                            template: "bfts content"
                        }
                    }
                });

Upvotes: 2

Views: 3237

Answers (1)

Aco Mitevski
Aco Mitevski

Reputation: 353

The bindings are available in the controller scope, so this.module must work.

I reproduced your code in a plnkr and found following errors.

  1. The main problem is that you use a "<" binding, which is a one-way binding. So it tries to access the "btfs" variable which is not defined in your scope, therefore undefined is absolutely correct output. To use a string use "@" see https://docs.angularjs.org/guide/component

    constructor() { this.bindings = { module: '@' } }

  2. dont inject the module var. just define it in your controller to satisfy typescript compiler.

    public module: string;

  3. you dont need controllerAs. The templates automatically gets the scope injected via $ctrl, see my example at medium. but not sure if thats critical

  4. as I described in my post its always a good idea to put angular.module calls at the bottom of the source file

modified code:

angular.module('goNoGo', []);


class LeftHandMenuComponent implements ng.IComponentOptions {


    public transclude: boolean = false;
    public controller: Function = LeftHandMenuComponentController;
    //public controllerAs: string = "vm";
    public template: string = "<div>module :{{$ctrl.module}}</div>";
    public bindings: any;

    constructor() {
        this.bindings = {
            module: '@'
        }
    }
}



class LeftHandMenuComponentController {

  menuStructure: IMenuStructure[];
  closeOthers: boolean = true;
  public module: string;

  static $inject = [];

  constructor() {
      console.log('binding2', this.module);
  }

  //public $onInit = (): void => {
    //  this.populateMenuStructure();
}

angular
    .module("goNoGo")
    .component("gonogoLefthandmenuComponent", new LeftHandMenuComponent());

angular.element(document).ready(function () {
  angular.bootstrap(document, ['goNoGo']);
});

you can play around in plnkr http://plnkr.co/edit/TVI9l8

Upvotes: 2

Related Questions