Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are changes done to $scope in directive's link function not reflected on UI?

AngularJS directives' link function change isolate scope data not reflected in UI.

Here is an example:

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

myApp.directive('myDirective', function () {
    return {
        restrict: 'A',
        template: '<span>Title: {{myParams.title}}</span>',
        scope: {
            myParams: '='
        },
        link: function ($scope) {
            // the new value is not reflected in ui
            $scope.myParams.title = 'this is myDirective';
        }
    };
});

HTML:

 <div my-directive my-params="{title: 'this is title'}"></div>

I want the HTML page to display this is myDirective but in fact it is this is title.

In addition, could you explain why it is displaying like this. Thanks

like image 511
fionsay Avatar asked Jun 17 '16 08:06

fionsay


1 Answers

The reason is that the my-params="{title: 'this is title'}" is a constant expression and not assignable. So even though you try to overwrite the 'title' property, it gets overwritten back from the constant. Check this fiddle. It contains your code and is set to work with Angular 1.4. With the difference that the directive is used once as above and once with a changable, non-constant value from a controller:

<div ng-app="app" ng-controller="Ctrl as ctrl">
  <div my-directive my-params="{title: 'this is title'}"></div>
  <div my-directive my-params="data"></div>
</div>

The second instance (non-constant expression) works.

Now try to change the Angular version to 1.2. Notice that now Angular throws an infinite digest error:

VM1033 angular.js:9101 Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: parentValueWatch; newVal: {\"title\":\"this is title\"}; oldVal: {\"title\":\"this is title\"}"],["fn: parentValueWatch; newVal: {\"title\":\"this is title\"}; oldVal: {\"title\":\"this is title\"}"],["fn: parentValueWatch; newVal: {\"title\":\"this is title\"}; oldVal: {\"title\":\"this is title\"}"],["fn: parentValueWatch; newVal: {\"title\":\"this is title\"}; oldVal: {\"title\":\"this is title\"}"],["fn: parentValueWatch; newVal: {\"title\":\"this is title\"}; oldVal: {\"title\":\"this is title\"}"]]

The expression given in the directive (i.e. my-params="{title: 'this is title'}") is trying to overwrite the directive scope attribute (always creating a new object in 1.2, hence the infinite digest).

like image 146
Nikos Paraskevopoulos Avatar answered Sep 30 '22 06:09

Nikos Paraskevopoulos