javascriptangularjsangularjs-directiveangularjs-controlleras

angular directive controller doesn't see passed parameters update


I have problems using controllerAs in angular directive. When the data is passed to the directive as parameter i want to do some simple transformation and pass it down to child directive. On initialisation parameter is empty. It is passed with ng-click event.

angular.module('myApp', [])
    .directive('testDirective', function() {
        var controller = function() {
            var vm = this;
            // when 'datasoure' is bound to the controller?
            console.log(vm);
            // I have to do some transformations here when the data is pushed to the directive 
            if (vm.datasource != undefined) {
                vm.direlements = vm.datasource.elements;
            }

        };
        return {
            controller: controller,
            controllerAs: 'ctrl',
            bindToController: true,
            scope: {
                datasource: '=',
            },
            template: '<div><li ng-repeat="item in ctrl.direlements">{{item}}</li></div>'
        }
    })
    .controller('TestCtrl', function() {
        var vm = this,
            current = {};

        vm.buttonClick = function() {
            console.log('buttonClick');
            vm.current = {
                elements: [{
                    'a': 1
                }, {
                    'b': 2
                }]
            }
        }
    });

HTML:

<body ng-app="myApp">
<div ng-controller="TestCtrl as test">
    <button ng-click="test.buttonClick()">push me</button>
    <test-directive  datasource="test.current"></test-directive>
</div>
</body>

Nothing happens here. Seems like controller doesn't track parameter changes. Plunkr


Solution

  • You had two issues in the code.

    So first thing, you are setting your controller variable direlements only on the init of the controller, but at that time the variable is undefined, because you set it up when you click. So you need a $watch in order to keep it updated and inject the $scope in the controller:

    vm.direlements = [];
          $scope.$watch(function() {
            return vm.datasource;
          }, function(oldValue, newValue) {
              if(typeof(newValue) !== 'undefined') {
                vm.direlements = vm.datasource.elements;
              }
          });
    

    Then inside your main controller you define at the beginning current as local variable, but you want it as vm variable, so you should use this:

    var vm = this;
    vm.current = {};
    

    All the other things are ok.

    So here your complete example:

    http://plnkr.co/edit/sALFVkSPIxVPOS42nOGu?p=preview