AngularJS ng-if and scopes

2019-01-25 05:08发布

问题:

I am trying to understand ng-if and scopes. As I am aware, ng-if creates a new child scope. Here is my issue:

View

<input ng-model="someValue1" />
<div ng-if="!someCondition">
    <input ng-model="$parent.someValue2" />
</div>

Controller

$scope.someCondition = true;

if ($scope.someCondition) {
    $scope.someValue2 = $scope.someValue1;        
}

If someCondition is set to true, then someValue2 should be the same as someValue1.

My problem is that I can't access someValue2 in both situations (true or false). How could I achieve this?

回答1:

Yes, ng-if creates a new child scope

To watch a model property in an ng-if, the rule-of-thumb is:

DO NOT USE THE SCOPE AS MODEL

e.g.

ng-if='showStuff' //here my scope is model **INCORRECT**
ng-if='someObject.showStuff' // ** CORRECT **

Use an object property in ng-model - then, even if ng-if creates the new child scope, the parent scope will have the changes.

To see a working Plunker, look here : http://jsfiddle.net/Erk4V/4/



回答2:

ngIf does indeed create a new scope using prototypal inheritance. What that means is that the ngIf's scope's prototype object is that of its parent's scope. So if the attribute isn't found on the ngIf instance of its scope it will look into its prototype objects chain for that attribute. However, once you assign an attribute to the instance of the scope it will no longer look into its inheritance chain for the attribute. Here's a link explaining prototypal inheritance used in JS: https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance

How to solve this:

Parent controller:

$scope.data = {someValue: true};

Child controller:

$scope.data.someValue = false

Because you're not hiding an attribute on its parent's scope, you're just mutating an object on its parent's scope, this will indeed alter the parent's data object. So in your case:

<input ng-model="data.someValue1" />
<div ng-if="!data.someCondition">
    <input ng-model="data.someValue2" />
</div>


回答3:

From what I'm aware of, the ng-if is purely a display level statement. You can use it to make some elements visible / invisible given certain values but I don't think it creates any kind of scope. What your HTML code will do is toggle the visibility of your secondary input.

If you'd like to switch your Value 2 to equal Value 1 whenever "someCondition" changes between false and true, then you can use $watch with something like this:

$scope.$watch(someCondition, function(){
  if (someCondition){
    $scope.someValue1 = $scope.someValue2
  }
})