我创建了一个带有单选按钮的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>
我可以根据需要多次选择每个选项,并且值一直到应用程序的范围变量。
我想更改单选按钮的创建,以便在选择对象数组上使用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>
Here is the working version fiddle以及我的指令代码的相关部分:
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);
};
}
here is the version that only works once:
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);
};
}
我对AngularJS来说是全新的,所以我完全有可能犯下一个非常基本的错误。有人能指出我正确的方向吗?
更新根据callmekatootie的建议,我将相关事件从ng-change
更改为ng-click
,并且每次都会触发。这将暂时解决,但我最初使用ng-change
,因为我认为ng-click
不适用于点击文字标签而非输入本身造成的更改,但实际上确实如此。但仍然不明白为什么ng-change
只会发射一次。
答案 0 :(得分:7)
问题的原因是ngRepeat
将为其子项创建新的范围(以及原型继承如何影响范围)。
Angular wiki 对范围继承的工作原理(以及常见的陷阱)有相当好的(彻底的)解释。
This answer 对一个非常相似(实际上)的问题几乎解释了这个问题。
在您的具体情况下,您可以介绍一个对象(例如local
)并指定environment
作为其属性):
scope.local = {environment: scope.environment};
scope.changeEnvironment = function(choice) {
scope.environment = choice.id;
};
然后你应该将你的模板绑定到“encaplulated”属性:
<input ... ng-model="local.environement" ... />
另请参阅此 short demo 。
<强>更新强>
这个答案旨在指出问题的根源 绝对建议使用不同的实现(如tasseKATT或Leon提议的实现)(以及更多“Angularish”)。
答案 1 :(得分:4)
使用对象而不是原始值:
app.controller('mainController', ['$scope', function (scope) {
scope.environment = { value: '' };
}]);
删除ng-change
和$watch
。 ng-model
就足够了(除非我误解了用例)。
演示: http://jsfiddle.net/GLAQ8/
可以找到关于原型继承的非常好的帖子here。
答案 2 :(得分:2)
你在ng-change事件中使用enviorement而不是$ parent.enviorement,它与重复范围有关,而不是enviorement变量所在的ng-repeat父范围,
ng-model="$parent.enviroment"
请注意,在这种情况下,您甚至不需要事件来更新环境,并且模型中的任何更改都会在单选按钮中显示