AngularJS track by $index引起的思考
今天写了一段程序,只是一个简答的table数据绑定,但是绑定select的数据之后,发现ng-change事件失去了效果,不知道什么原因。
主要用到的代码如下:
<div id="right" ng-app="myApp" ng-controller="targetControl">
<select ng-model="indexSelect" data-size="4" ng-option="s for s in indexs track by $index"
id="stIndex" class = "selectpicker show-trick form-controller" ng-change="onIndexChanged()">
</select>
<table>
<tr>
<th>版本名称</th>
<th>达标值</th>
</tr>
<tr ng-repeat="x in lists track by $index">
<td>{{x.CVersion}}</td>
<td contenteditable = "true" ng-blur="submit($event)" title='{{x.duName}}'>{{x.TargetVal}}</td>
</tr>
</table>
</div>
<script type="text/javascript">
angular.module("myApp",[]);
angular.module("myApp").controller("targetControl",function($scope,$http){
$http({
url:*******,
method:"Get"
}).success(function(data)
{
$scope.index = data;
}).error(function(data))
{
alert("error");
};
$scope.onIndexChanged()
{
alert($("#stIndex option:selected").text());
};
//当达标值那一列值发生变化时,响应该事件
$scope.submit = function(obj)
{
//obj.target可以获取到当前td对象的所有属性,例如obj.target.title
}
});
</script>
刚开始调试的时候,是报了一个错:
Error:[ngRepeat:dupes] http://******
调查发现,是因为indexs里有重复数据导致的;
好像是只有有一项有重复数据就会报错(我测试的时候,仅达标值这一些列有重复元素),必须加上track by $index才行。
加上track by $index相当于给重复数据加上了序号,重复的数据就相当于不重复了。
然后我在给select标签去重的时候,也加上了track by $index,结果发现加上之后:
1、select的重复元素并没有去除;
2、无论选择select的哪个值,ng-change事件只能触发一次,后面都不能触发了;
3、select选项默认选中租最后一项,及时设置另一项为selected状态都没用。
经过调查后发现,track by $index对select标签去重并没有什么作用,而且select标签有重复数据时也不会报错。
ng-change事件不触发的原因是,加上track by $index之后,ng-model的值不会再发生变化,永远等于select标签的最后一个值,
看起来就像ng-change方法没有触发的样子。
select标签去除重复有另一种过滤机制:
app.filter('unique',function(){
return function(collection, keyname){
var output = [];
keys = [];
angular.forEach(collection, function(item){
var key = item[keyname];
if(keys.indexof(key) === -1){
keys.push(key);
output.push(item);
}
});
return output;
}
})
<div ng-repeat="item in items | unique:'id'"></div>
初步记录在此,后续再分析具体原因。