简体   繁体   中英

Angular 1.5: Access bindToController properties inside controller

I'm learning how to properly use the bindToController feature of custom directives and wondering how to access the properties you declare in the bindToController object from the directive controller.

var myApp = angular.module('myApp',[])
  .directive('myDir', MyDir)
  .controller('MyCtrl',['$scope', MyCtrlFn]);

function MyCtrlFn($scope) {
  var ctrl = this;
  this.ctrlStr = '';
  this.ctrlAsStr = '';
  $scope.$watch(this.name, function(newValue) {
    if(newValue) ctrl.ctrlStr += ' '+newValue;
  })
  $scope.$watch('ctrl.name', function(newValue) {
    if(newValue) ctrl.ctrlAsStr += ' '+newValue;
  })
}

function MyDir() {
  return {
    template: '<div>{{ctrl.name}}</div>'+
    '<div>CtrlStr: {{ctrl.ctrlStr}}</div>'+
    '<div>CtrlAsStr: {{ctrl.ctrlAsStr}}</div>',
    scope: {},
      bindToController: {
          name: '='
      },
    restrict: 'E',
    controller: 'MyCtrl',
    controllerAs: 'ctrl'
  }
}

jsFiddle here: http://jsfiddle.net/jrtc1bLo/2/

So I thought the properties were bound to the controller but it seems they're rather bound to the controller alias in the scope.

What's the good way to access them from the controller ?

Thanks

If you correct your first watcher, you will see that your controller is bound correctly.

function MyCtrlFn($scope) {
  var ctrl = this;
  this.ctrlStr = '';
  this.ctrlAsStr = '';
  //DO THIS
  $scope.$watch(function(){return ctrl.name}, function(newValue) {    
  // NOT THIS
  //$scope.$watch(this.name, function(newValue) {
    if(newValue) ctrl.ctrlStr += ' '+newValue;
  })
  $scope.$watch('ctrl.name', function(newValue) {
    if(newValue) ctrl.ctrlAsStr += ' '+newValue;
  })
}

The first argument to $watch is either a function that is evaluated every digest cycle or an Angular expression in string form which is evaluated each digest cycle.

With the correction, both watchers will see the changes.

Take a look at this example:

angular
    .module('form')
    .controller('FormGroupItemController', FormGroupItemController)
    .directive('formGroupItem', formGroupItem);

function FormGroupItemController(){}

function formGroupItem() {
    var directive = {
        restrict: 'A',
        scope: {
            model: '=',
            errors: '=',
            submit: '='
        },
        bindToController: true,
        controller: 'FormGroupItemController as vm',
        templateUrl: 'app/form/form-group-item.html'
    };

    return directive;
}

As you can see, I have a form-group-item directive. I use it in my HTML like so:

<div form-group-item model="vm.username" errors="vm.errors" submit="vm.updateUsername"></div>

Here I take three things from the scope that the directive was used in, and I essentially duplicate them (bind them to the controller) of the directive itself. Those three things are: model , errors , and submit .

The errors are a bag of possible errors (array), the model is just a value to watch, and the submit is a submit function.

Now those three things are within the scope of FormGroupItemController , and I can use them in the form-group-item.html as a $scope or controllerAs , whichever I specified. In this case, I use controllerAs syntax.

So before the directive has anything binded to it's controller, it's just an empty constructor like this:

function FormGroupItemController() {}

After the bind, it will look like this:

function FormGroupItemController() {
    this.model = 'blah';
    this.errors = [...];
    this.submit = function(...) {...}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM