【发布时间】:2016-07-28 18:15:01
【问题描述】:
我刚刚在 Angular.js 中发现了一个奇怪的功能/错误。
假设我们有一个选择框,其中的选项由 ngOptions 指令填充。我们使用 ngChange 指令在选择框上设置了一个更改监听器。
<select ng-model="model" ng-options="item for item in list" ng-change="foo()"></select>
我们定义范围如下:
$scope.list = [1,2,3,4,5];
$scope.model = 3;
$scope.foo = function() {
console.log("change");
};
然后我们在代码中的某个地方像这样重置数组:
$scope.list = [];
如果我们查看控制台,我们可以看到函数 foo() 被调用并且文本 "change" 被记录。但是,用户没有触摸选择框,也没有更改所选值。根据文档
ngChange 表达式仅在输入发生更改时进行评估 value 会导致将新值提交给模型。
它将不被评估:
- 如果从 $parsers 转换管道返回的值没有改变
- 如果输入继续无效,因为模型将保持为空
- 如果模型以编程方式更改,而不是通过更改输入值
输入值未更改。模型未更改。只有用于生成选项的数组(使用对象时行为相同)以编程方式进行了更改。
通过检查 select 元素,我还发现 ng-dirty 类已设置为该元素,即使用户从未触摸过选择框(ng-untouched 类仍然设置)。
为什么会这样?这是一个我无法理解的奇怪功能还是一个错误?难道我做错了什么?你知道这个问题的解决方案吗?
【问题讨论】:
-
输入值 is 在您修改用于生成选项的数组后立即更改。
-
这不是真的。我可以随意修改数组(添加/删除元素,替换整个数组)并且模型不会改变,不会评估 ngChange 表达式。这是预期的行为。只有空/未定义/空数组/对象会导致意外行为。
-
你有
$scope.model = 3;。在您看来,输入{{model}}并在您调用任何代码集$scope.list = []时观察变化。 -
与此同时,我还发现
model设置为null,而list不再包含所选值。但你的评论说有些不同。 如何修改数组很重要。但这仍然是一种奇怪且出乎意料的行为。当您为模型分配一个不在列表中的值时,没有问题。你可以这样做,一个带有新值的空选项将被添加到选择框中。那么为什么当你以相反的顺序执行时,模型应该设置为null? -
最重要的是:在这种情况下,模型是由角度(由程序更改触发)而不是用户更改的。因此,没有逻辑理由来评估 ngChange 表达式,该表达式是为用户通过单击更改输入的情况设置的。也许我应该访问 Angular 的 github 页面来讨论这个“功能”。你怎么看?
标签: angularjs drop-down-menu ng-options angularjs-ng-change