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-change为ng-click,并且每次都会触发.这将作为一个解决方案现在,但我最初使用,ng-change因为我不认为ng-click将适用于通过单击文本标签而不是输入本身引起的更改,但事实上它确实如此.但仍然不明白为什么ng-change只会发射一次.
问题的原因是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
这个答案旨在指出问题的根源.绝对建议
使用不同的实现(如tasseKATT或Leon提出的实现)(以及更多"Angularish").
使用对象而不是原始值:
app.controller('mainController', ['$scope', function (scope) {
scope.environment = { value: '' };
}]);
Run Code Online (Sandbox Code Playgroud)
删除ng-change和$watch。ng-model就足够了(除非我误解了用例)。
演示: http: //jsfiddle.net/GLAQ8/