javascript ngIf 内的绑定元素不更新绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21512182/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 21:04:03  来源:igfitidea点击:

bound element inside ngIf does not update binding

javascriptangularjsangularjs-directive

提问by elewinso

I have written a angularjs directive. in this directive's template I have added an ngIf directive and within it I display an input that is bound to my directive's scope.

我写了一个 angularjs 指令。在该指令的模板中,我添加了一个 ngIf 指令,并在其中显示了一个绑定到指令范围的输入。

<div ng-if="bool"><input ng-model="foo"></div>

I noticed, after a lot of trial and error that the ngIf directive cause the model to not get updated when the input text is changed. If I change it to ngShow everything works as expected.

我注意到,经过多次反复试验,ngIf 指令导致模型在输入文本更改时无法更新。如果我将其更改为 ngShow,一切都会按预期进行。

I am looking for an explanation of this difference

我正在寻找这种差异的解释

I have created a jsfiddle here

我在这里创建了一个 jsfiddle

回答by dimirc

It's happening because ngIf creates a new child scope, so if you want to bind to the same scope as the other inputs, we can go one level down with $parent. Check hereto understand more about scope inheritance

这是因为 ngIf 创建了一个新的子作用域,所以如果你想绑定到与其他输入相同的作用域,我们可以使用 $parent 向下一级。检查此处以了解有关范围继承的更多信息

  angular.module('testApp', [])
  .directive('testDir', function () {
    return {
      restrict: 'A',
      template: '<input ng-model="foo"><input ng-model="foo">' +
         '<div ng-if="bool"><input ng-model="$parent.foo"></div>',
      link: function (scope, elem, attrs) {
        scope.foo = "bar";
        scope.bool = true;       
      }
    }
  });

Take a look to new jsfiddle

看看新的jsfiddle

回答by Ilan Frumer

This happens because you use a primitive on the scope.

发生这种情况是因为您在作用域上使用了原语。

ngIfcreates a new child scope and it shadows the value from the parent scope.

ngIf创建一个新的子作用域,并从父作用域中隐藏该值。

Use the dot notation instead:

改用点表示法:

<div ng-if="bool"><input ng-model="data.foo"></div>


From Understanding Scopes wiki:

了解范围维基:

Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope.

It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works.

New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved.

This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models.

作用域继承通常很简单,你通常甚至不需要知道它正在发生......直到你尝试将 2 路数据绑定(即表单元素、ng-model)绑定到一个基元(例如,数字、字符串、 boolean) 在子作用域内在父作用域上定义。

它不像大多数人期望的那样工作。发生的情况是子作用域获得了自己的属性,该属性隐藏/隐藏了同名的父属性。这不是 AngularJS 正在做的事情——这就是 JavaScript 原型继承的工作方式。

新的 AngularJS 开发人员通常没有意识到ng-repeat、ng-switch、ng-view 和 ng-include 都创建了新的子作用域,因此当涉及到这些指令时,问题往往会出现。

通过遵循始终具有 '.'的“最佳实践”,可以轻松避免原语的这个问题在你的 ng-models 中

回答by zszep

Define foo as an object with properties. This all has to do with javascript prototypical inheritance. See your modified jsfiddle.

将 foo 定义为具有属性的对象。这一切都与 javascript 原型继承有关。查看您修改后的jsfiddle

 angular.module('testApp', [])
  .controller('MyController',function($scope){
      $scope.foo = {bool: true};
  })
  .directive('testDir', function () {
    return {
      restrict: 'A',
      template: '<input ng-model="foo.x"><input ng-model="foo.x"><div ng-if="foo.bool"><br/>changing me does not update the other inputs because i am in an ngIf if in ngShow all works just fine<input ng-model="foo.x"></div>',
      link: function (scope, elem, attrs) {
        scope.foo.x = "bar";
        scope.foo.bool = true;       
      }
    }
  });

For a detailed info see this video.

有关详细信息,请参阅此视频