我有一个包含大量文本框的页面,类似Excel的布局。每列代表一个对象,该列中的单元格包含对象的属性。当单元格中的值发生更改(当单元格失去焦点时触发),我需要知道更改的对象和属性,以便我可以将值复制到其他所选对象中的相同属性。
我有这个工作,但这是一种天真的方法,我认为最好将其封装在一个指令中。问题是我能够编写的指令与我的第一个解决方案一样冗长,似乎并没有改进。
first version只是将对象和属性名称传递给更改处理函数。
<td>
<input ng-model="person.firstName"
ng-change="personChanged(person, 'firstName')"
ng-model-options="{updateOn: 'blur'}" />
</td>
$scope.personChanged = function(person, property) {
alert(person.personId + ' : ' + property);
}
second version使用指令。
<td>
<input ng-model="person.firstName"
name-changed person="person" property="'firstName'" />
</td>
myApp.directive('nameChanged', function() {
return {
restrict: 'A',
scope: {
person: '=',
property: '='
},
link: function(scope, element, attrs){
element.bind('change', function(e){
alert(scope.person.personId + ' : ' + scope.property);
});
}
};
});
在这两个解决方案中,我在属性中声明对象和属性名称,这似乎是多余的,因为我已经通过ngModel提供了两者。这样做的正确方法是什么?
答案 0 :(得分:1)
当您编写ngModel="person.firstname"
时,angular将侦听firstname属性上的任何更改,并且它只会在您的ngModel中保留firstname的值(请查看ngModel和ngModelController上的文档)。这意味着您必须在指令范围内传递其他信息(例如person.id,property)
你应该尽可能避免双向绑定。使用&#39;&amp;&#39;和&#39; @&#39;将属性绑定到指令范围时。
指令的优化版本:
myApp.directive('nameChanged', function() {
return {
require: 'ngModel',
restrict: 'A',
scope: {
person: '&',
property: '@'
},
link: function(scope, element, attrs, ngModel){
element.bind('change', function(e){
alert(scope.person().personId + ' : ' + scope.property + ', value is : ' + ngModel.$modelValue)
// dispatch your change to upper scopes
scope.$emit('nameChanged', {personId : scope.person().personId, property: scope.property, value : ngModel.$modelValue});
});
}
};
});
然后在你的控制器中处理这个事件:
myApp.controller('peopleController', function($scope) {
$scope.people = [new Person(1, 'Homer', 'Simpson'), new Person(2, 'Ned', 'Flanders'), new Person(3, 'Otto', 'Mann')];
$scope.$on('nameChanged', function(event, change){
// changed detected inside one of ours dirctives
console.log('changed detected from controller', change)
// do what you want with he new value : 'change.value'
})
});
请注意,事件名称应位于.constant模块中。它的可维护性更好。
您可以通过两种方式(使用ng-change和范围内的fn)或使用isolate scope指令实现您想要的任何方式。就个人而言,我喜欢在指令中做到这一点,以隔离责任,但这取决于你。