{{...">

Angular does not update associated property

Fiddle

HTML:

<div ng-controller="MyCtrl">
    <button my-event-directive>Click me</button>
    <div>{{secret}}</div>
</div>

      

JS:

var myApp = angular.module('myApp',[]);

myApp.directive('myEventDirective', function() {
      return {
        link: function(scope, element) {
            element.on('click', function(event){
                scope.$emit('myEvent', {secret: 'aaa'}); 
            });
        }
      }
})

function MyCtrl($scope) {
    $scope.secret = 'bbb';
    $scope.$on('myEvent', function(event, data){
        alert('event received!');
        $scope.secret = data.secret;
    });
}

      

After pressing the button, the event is received in the controller (a warning appears). However, the binding {{secret}}

does not update its value. Why?

My event creation is more complicated in real code, of course.

+3


source to share


3 answers


As @Cherinv pointed out in a comment, when you change the outsite scope attributes to an Angular method, $apply

you have to call it manually. @runTarm also suggested that the event dispatcher should use $apply

because the listeners are freed from remembering it. So:

scope.$emit('myEvent', {secret: 'aaa'});

      

should be changed to:



scope.$apply(function() {
    scope.$emit('myEvent', {secret: 'aaa'});
});

      

$apply

is detailed in the following article: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

+3


source


USE $ scope. $ apply (). NOW the changes will be noticed and the page will be updated.



var myApp = angular.module('myApp',[]);

        myApp.directive('myEventDirective', function() {
              return {
                link: function(scope, element) {
                    element.on('click', function(event){
                        scope.$emit('myEvent', {secret: 'aaa'}); 
                    });
                }
              }
        })

        function MyCtrl($scope) {
            $scope.secret = 'bbb';
            $scope.$on('myEvent', function(event, data){
                alert('event received! secret is ' + data.secret);

                 $scope.$apply(function () {
                    $scope.secret = data.secret;        
                 });
            });
        }

      

+1


source


You can try changing the binding to happen to object.value rather than value. Perhaps this is the case where angular is unable to track an immutable property change.

<div ng-controller="MyCtrl">
    <button my-event-directive>Click me</button>
    <div>{{data.secret}}</div>
</div>

var myApp = angular.module('myApp',[]);

myApp.directive('myEventDirective', function() {
      return {
        link: function(scope, element) {
            element.on('click', function(event){
                scope.$emit('myEvent', {secret: 'aaa'}); 
            });
        }
      }
})

function MyCtrl($scope) {
    $scope.data = {
        secret: 'bbb'
    };
    $scope.$on('myEvent', function(event, data){
        alert('event received!');
        $scope.data.secret = data.secret;
    });
}

      

This should work.

PS since you always see the callable message, which means you don't need to call the scope. $ apply to call scope and assigned value digests, problem is angular can't look at immutable values ​​(maybe)

0


source







All Articles