zorza
zorza

Reputation: 2884

Update directive scope when attribute changes using controllerAs syntax

What I need is to inject the data inside a directive dependent on the value passed to this directive via HTML element attribute value, which changes dynamically.

Here's my code:

angular.module('test', [])
    .controller('ctrl', function (dataService) {
        var vm1 = this;
        vm1.data = dataService;
        vm1.change = function () {
            vm1.data.testValue = !vm1.data.testValue;
        }
    })
    .directive('myDrct', function () {
        return{
            restrict: 'E',
            controller: 'drctCtrl',
            controllerAs: 'vm',
            scope:{
                passedValue: '@pass'
            },
            template: 'Actual value in directive: {{vm.passedValue}}'
        }
    })
    .controller('drctCtrl', function ($scope) {
        var vm = this;
        vm.passedValue = $scope.passedValue;
        $scope.$watch('watcher', function () {
            vm.passedValue = $scope.passedValue;
        })
    })
    .factory('dataService', function () {
        return{
            testValue: true
        }
    });
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<div ng-app="test" ng-controller="ctrl as vm">
    Value passed as a parameter to directive: {{vm.data.testValue}}
    <button ng-click="vm.change()">change</button>
    <div>
        <my-drct pass="{{vm.data.testValue}}"></my-drct>
    </div>
</div>

And here is a demo plunker:

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

As suggested in many similar topics on StackOverflow, I've tried $scope.$watch, but I must be doing something wrong. The value gets inserted to the directive once and it doesn't get updated when the attribute value changes.

What shoud I change in the watcher function to get it to work? Or maybe this approach is not good at all in my case and I should try something else?

EDIT: I must use "controllerAs vm" syntax, since this code is just a part of a bigger app already dependent on it.

Upvotes: 1

Views: 868

Answers (1)

rnrneverdies
rnrneverdies

Reputation: 15627

The only thing you needs to change in your code in controller: vm.scope = $scope; instead of vm.passedValue = $scope.passedValue; and in a template change {{vm.passedValue}} to {{vm.scope.passedValue}}

Plunker: http://plnkr.co/edit/q8JBFu4FD5ECPFHYlPg6?p=preview

angular.module('test', [])
    .controller('ctrl', function (dataService) {
        var vm1 = this;
        vm1.data = dataService;
        vm1.change = function () {
            vm1.data.testValue = !vm1.data.testValue;
        }
    })
    .directive('myDrct', function () {
        return{
            restrict: 'E',
            controller: 'drctCtrl',
            controllerAs: 'vm',
            scope:{
                passedValue: '@pass'
            },
            template: 'Actual value in directive: {{vm.scope.passedValue}}'
        }
    })
    .controller('drctCtrl', function ($scope) {
        var vm = this;
        vm.scope = $scope;

    })
    .factory('dataService', function () {
        return{
            testValue: true
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="ctrl as vm">
  Value passed as a parameter to directive: {{vm.data.testValue}}
  <button ng-click="vm.change()">change</button>

  <div>
    <my-drct pass="{{vm.data.testValue}}"></my-drct>
  </div>

</div>

Upvotes: 2

Related Questions