ng-change事件仅在使用ng-repeat创建时为每个单选按钮触发一次

Dan*_*nny 11 angularjs angularjs-directive

我创建了一个带有单选按钮的AngularJS指令来控制我的页面将查询的环境并将其添加到我的页面.我正在使用双向绑定将名为变量的局部范围变量映射environment到具有相同名称的app变量.当我在模板中明确地创建单选按钮时,它似乎运行良好(在我实际使用的代码中,我templateUrl仍然使用相同的问题).

<div>
    <label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(1)" value="1" />Testing</label>
    <label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(2)" value="2" />Production</label>
</div>
Run Code Online (Sandbox Code Playgroud)

我可以根据需要多次选择每个选项,并且值一直到应用程序的范围变量.

我想改变单选按钮的创建,以便ng-repeat在选择对象数组上使用.它创建选项,并捕获ngChange事件,但每次选择只能捕获一次.

<label ng-repeat="choice in choices">
    <input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(choice)" value="{{ choice.id }}" />{{ choice.name }}
</label>
Run Code Online (Sandbox Code Playgroud)

这是工作版小提琴和我的指令代码的相关部分:

template: '<div>'
            + '<label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(1)" value="1" />Testing</label>'
            + '<label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(2)" value="2" />Production</label>'
            + '<div>Directive environment: {{ environment }}</div>'
            + '</div>',
link: function(scope, element, attributes) {

    scope.changeEnvironment = function(choiceID) {
        console.log('SELECTED environment ' + choiceID);
        scope.environment = choiceID;
        console.log('directive environment = ' + scope.environment);
    };

}
Run Code Online (Sandbox Code Playgroud)

以下是仅适用一次的版本:

template: '<div><label ng-repeat="choice in choices">'
            + '<input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(choice)" value="{{ choice.id }}" />{{ choice.name }}'
            + '</label>'
            + '<div>Directive environment: {{ environment }}</div>'
            + '</div>',
link: function(scope, element, attributes) {
    scope.choices = [
        { id: 1, name: "Testing" },
        { id: 2, name: "Production" }
    ];

    scope.changeEnvironment = function(choice) {
        console.log('SELECTED environment ' + choice.id);
        scope.environment = choice.id;
        console.log('directive environment = ' + scope.environment);
    };

}
Run Code Online (Sandbox Code Playgroud)

我对AngularJS来说是全新的,所以我完全有可能犯了一个非常基本的错误.谁能指出我正确的方向?

更新根据callmekatootie的建议,我将有问题的事件更改ng-changeng-click,并且每次都会触发.这将作为一个解决方案现在,但我最初使用,ng-change因为我不认为ng-click将适用于通过单击文本标签而不是输入本身引起的更改,但事实上它确实如此.但仍然不明白为什么ng-change只会发射一次.

gka*_*pak 8

问题的原因是ngRepeat它将为其子代创建新的范围(以及原型继承如何影响范围).

角维基具有的范围继承是如何工作的一个相当不错的(和透彻的)的解释(和常见的陷阱).

对非常相似(本质上)问题的答案几乎解释了这个问题.

在您的特定情况下,您可以引入一个对象(例如local)并指定environment为其属性):

scope.local = {environment: scope.environment};
scope.changeEnvironment = function(choice) {
    scope.environment = choice.id;
};
Run Code Online (Sandbox Code Playgroud)

然后,您应该将模板绑定到"encaplulated"属性:

<input ... ng-model="local.environement" ... />
Run Code Online (Sandbox Code Playgroud)

另见这个简短的演示.


UPDATE

这个答案旨在指出问题的根源.绝对建议
使用不同的实现(如tasseKATTLeon提出的实现)(以及更多"Angularish").


tas*_*ATT 4

使用对象而不是原始值:

app.controller('mainController', ['$scope', function (scope) {
  scope.environment = { value: '' };
}]);
Run Code Online (Sandbox Code Playgroud)

删除ng-change$watchng-model就足够了(除非我误解了用例)。

演示: http: //jsfiddle.net/GLAQ8/

关于原型继承的非常好的帖子可以在这里找到。