-->

Scope variable is not updated on ng-click in views

2020-07-24 06:32发布

问题:

I have a problem with the following code: Plunkr.

When I click the button, the ng-click changes the variable var1 in scope. But apparently this variable is not updated in view, which I have created with UI Router. It looks like the scope have been copied inside the same controller.

The problem disappears in two situations: when I use {{$parent.var1}} instead of {{var1}}from inside my view, OR when I remove controller: 'MainCtrl' declaration from my state.

Can anyone clarify what's going on and how to avoid such problems? I like the solution with removing the controller declaration but how Angular UI Router will figure out which controller to use?

回答1:

Controllers and some directives that add elements to the dom create their own scope (ng-if, ng-switch, ng-repeat, ng-view etc.). You can use the AngularJS Batarang chrome extension to help debug them. The values are inherited, but setting the value in a child scope breaks the inheritance. You can create your own service, or you can use an object inherited from a parent scope and as long as you're setting properties on the inherited object you'd be fine. Since you're setting the value in your controller I use || to only set the value initially if an inherited value isn't there. (plnkr):

app.controller('MainCtrl', function($scope, globals) {
  $scope.var1 = 1;
  $scope.obj = $scope.obj || {var1: 1};
  $scope.g = globals; // for access in the page
  $scope.onClick = function() {
    globals.var1++;
    $scope.var1++;
    $scope.obj.var1++;
  };
});

app.service('globals', function() {
  this.var1 = 1;
  return this;
});


回答2:

Each controller defines its own scope. Each sub-view has its own controller.

app.controller('MainCtrl', function($scope) {

    $scope.var1=1;

});

this defines a controller construction, which takes a new scope, creating a new variable. if you want to alter the parent-scope variable, you have to switch the following code:

app.controller('MainCtrl', function($scope) {

    if ($scope.$parent.var1 == undefined) {
        $scope.$parent.var1 = 0;
    };

});

otherwise you'll be creating a new variable in this child scope, instead of accesing the parent scope. the button handler accesses its own scope, which is the parent scope of the scope where you want to initialize the variable.

Notes: I put 0 since the 1 was never shown (the state is switched, the variable initialized, and then incremented, without letting the 1 be shown).