PeteGO
PeteGO

Reputation: 5791

Angular - changes to directive controller's scope aren't reflected in view

Changes to my scope variable foo are getting updated in the html. When that value is change inside the scope of a directive's controller, it isn't updating in the html.

What do I need to do to make it update?

I have a simple example:

app.js

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

app.controller('ctrl', function($scope) {
  $scope.foo = 99;

  $scope.changeValue = function() {
    $scope.foo = $scope.foo + 1;
  }
});

app.directive('d1', function(){
  return {
    restrict: 'E',
    scope: {
      theFoo: '='
    },
    templateUrl: 'd1.html',
    controller: 'd1Ctrl',
  }
});

app.controller('d1Ctrl', function($scope) {
  $scope.test = $scope.theFoo;
});

d1.html

<div>
  <p>The value of foo is '{{theFoo}}'.</p>
  <p>The value of test is '{{test}}'.</p>
</div>

inside index.html

<d1 the-foo='foo'>
</d1>

<button ng-click='changeValue()'>change value</button>

So in summary, {{theFoo}} is updating, but {{test}} isn't. Why?

Upvotes: 0

Views: 770

Answers (3)

Priyamal
Priyamal

Reputation: 2969

here you have isolated the scope of the directive, so test is not visible to the d1.html, if you need to change test along with the theFoo you must first make it visible to the directive by

app.directive('d1', function(){
  return {
    restrict: 'E',
    scope: {
      theFoo: '=',
      test : '=' //getting test as well
    },
    templateUrl: 'd1.html',
    controller: 'd1Ctrl',
  }
});

and in index.html you should pass the value to the test by <d1 the-foo='foo' test='foo'></d1>

in the above code your controller is not much of a use , code will work fine even without this part controller: 'd1Ctrl'. with this example you dont have to use $watch.

Upvotes: 0

charlietfl
charlietfl

Reputation: 171669

The reason is that $scope.foo value is a primitive.

In the directive controller you only assign $scope.test once when controller initializes. Primitives have no inheritance the way objects do so there is nothing that would change $scope.test after that initial assignment

If you used an object instead to pass in ... inheritance would be in effect and you would see changes...otherwise you would need to watch $scope.theFoo and do updates to $scope.test yourself

Upvotes: 1

jusopi
jusopi

Reputation: 6813

The code you have in your controller only initializes to that value if it is indeed set at the time the controller is linked. Any subsequent changes are not going to work.

If you want to bind any subsequent changes, then you need to set a $watch statement either in your controller or a link function.

$scope.$watch( 'theFoo', function(val){ $scope.test = val; })

updated plunker - http://plnkr.co/edit/eWoPutIJrwxZj9XJu6QG?p=preview

Upvotes: 1

Related Questions