我有通过ng-repeat创建的数组的输入列表。我想检查它们中是否有任何重复的值。如果发现任何重复值,则显示错误消息。 我在 JS FIDDLE
中找到了我想要的东西<tr ng-repeat="person in persons">
<td>
<ng-form name="personForm">
<div ng-class="{ 'has-error' :
personForm.personName.$invalid }">
<input type='text'
name="personName"
ng-class="empty"
ng-model="person.name"
ng-change="verifyDuplicate()"/>
</div>
</ng-form>
<div class='error'
ng-if='person.isDuplicate'>
Duplicate.
</div>
</td>
$scope.verifyDuplicate = function() {
var sorted, i;
sorted = $scope.persons.concat().sort(function (a, b) {
if (a.name > b.name) return 1;
if (a.name < b.name) return -1;
return 0;
});
for(i = 0; i < $scope.persons.length; i++) {
sorted[i].isDuplicate = ((sorted[i-1] && sorted[i-1].name == sorted[i].name) || (sorted[i+1] && sorted[i+1].name == sorted[i].name));
}
};
所以我在 Plunker
中实现了这一点<div ng-repeat="item in csTagGrp">
<div ng-repeat="person in item.csTags">
<ng-form name="personForm">
<div ng-class="{ 'has-error' :
personForm.personName.$invalid }">
<input type='text' name="personName" ng-class="empty" ng-model="person.keys" ng-change="verifyDuplicate()" />
</div>
</ng-form>
<div class='error' ng-if='person.isDuplicate'>
Duplicate.
</div>
</div>
</div>
$scope.verifyDuplicate = function() {
var sorted, i;
sorted = $scope.csTagGrp.csTags.concat().sort(function(a, b) {
if (a.name > b.name) return 1;
if (a.name < b.name) return -1;
return 0;
});
for (i = 0; i < $scope.csTagGrp.csTags.length; i++) {
sorted[i].isDuplicate = ((sorted[i - 1] && sorted[i - 1].name == sorted[i].name) || (sorted[i + 1] && sorted[i + 1].name == sorted[i].name));
}
};
但看起来由于某种原因它不起作用。我在这里使用不同的嵌套对象数组。我在这里做错了什么?
提前致谢。
答案 0 :(得分:3)
它不起作用,因为您在sort函数中有错误的键名,并且您正在尝试使用嵌套对象。
只需修改它就可以使它与数组中的第一个对象一起使用。您需要遍历每个对象,以使其适用于所有对象。
$scope.verifyDuplicate = function() {
var sorted, i;
sorted = $scope.csTagGrp[0].csTags.concat().sort(function(a, b) {
if (a.keys > b.keys) return 1;
if (a.keys < b.keys) return -1;
return 0;
});
for (i = 0; i < $scope.csTagGrp[0].csTags.length; i++) {
sorted[i].isDuplicate = ((sorted[i - 1] && sorted[i - 1].keys == sorted[i].keys) || (sorted[i + 1] && sorted[i + 1].keys == sorted[i].keys));
}
};
因为您正在使用嵌套对象,所以这将成为一个稍微复杂的问题。您有一个对象数组,其中也包含数组。如果你(可以)把所有东西放到一个更平坦的物体上,那很简单。
csTagGrp[0]
告诉它访问csTagGrp数组中的第一个对象,即:
{
"csTagTitle": "Action",
"csTags": [{
"keys": "1",
"tags": "Quick Win"
}, {
"keys": "2",
"tags": "follow up with respondent"
}, {
"keys": "3",
"tags": "process imporvement"
}, {
"keys": "4",
"tags": "Large Fix"
}, {
"keys": "5",
"tags": "use in presentation"
}]
}
所以现在sorted
访问csTagGrp数组中[0]对象中的csTags数组,并对该数组中的所有keys
执行排序。到现在为止还挺好。但是使用此处的对象结构,您需要遍历两个数组(即csTagGrp中的所有对象,以及每个csTagGrp对象中的每个csTags数组)并对所有数组执行排序。这通常涉及多个for循环。
为了实现这一点,我将所有csTags数组(使用for循环)连接成一个新数组preSort
,然后传递给sort。这给了我们所需的(一个平面数组)来检查所有csTags数组的重复项。
$scope.verifyDuplicate = function() {
var preSort = [],sorted, i, c = $scope.csTagGrp;
for(i = 0; i < c.length; i++) {
preSort = preSort.concat(c[i].csTags);
}
sorted = preSort.concat().sort(function(a, b) {
if (a.keys > b.keys) return 1;
if (a.keys < b.keys) return -1;
return 0;
});
console.log(sorted)
for (i = 0; i < preSort.length; i++) {
sorted[i].isDuplicate = ((sorted[i - 1] && sorted[i - 1].keys == sorted[i].keys) || (sorted[i + 1] && sorted[i + 1].keys == sorted[i].keys));
}
};
});
答案 1 :(得分:1)
不幸的是,存在很多问题,但我相信没有什么是不可能克服的。最大的问题在于数据结构的差异。在最初的小提琴中,数据是一个简单的数组:
$scope.persons = [
{name: 1},
{name: 2},
{name: 3}
];
而在你的plunker中,数据(正如你已经提到的)嵌套了很多:
$scope.csTagGrp = [{
"csTagTitle": "Action",
"csTags": [{
"keys": "1",
"tags": "Quick Win"
}, {
"keys": "2",
"tags": "follow up with respondent"
}] // snipped contents for brevity
}, {
"csTagTitle": "Topicality",
"csTags": [{
"keys": "6",
"tags": "Root cause"
}, {
"keys": "7",
"tags": "Symptom"
}] // snipped contents
}, {
// snipped rest for brevity
}]
...所以你不能使用这样的东西(来自你的plunker):
sorted = $scope.csTagGrp.csTags.concat().sort(function(a, b) {
if (a.name > b.name) return 1;
if (a.name < b.name) return -1;
return 0;
});
for (i = 0; i < $scope.csTagGrp.csTags.length; i++) {
sorted[i].isDuplicate = ((sorted[i - 1] && sorted[i - 1].name == sorted[i].name) || (sorted[i + 1] && sorted[i + 1].name == sorted[i].name));
}
问题是:
$scope.csTagGrp
是数组对象(每个对象都有csTags
属性),它不是对象,其中{{1}属性
csTags
是$scope.csTagGrp.csTags
- &gt;尝试在undefined
上调用concat()
不会 - 自然 - 工作undefined
内的单个对象中访问csTags
属性,例如:$scope.csTagGrp
但是再次,这只会排序第一个sorted = $scope.csTagGrp[0].csTags.concat().sort(function(a, b) {
内的对象,而不是全部引出了下一个问题:原始的重复验证有效,因为它只是对平面数组进行排序。使用嵌套数组,此方法仅适用于单个组,而不适用于$scope.csTagGrp
$scope.csTagGrp
内的每个对象,这就是它) 但是如果(并且我怀疑 时)你想要检测每个对象中的重复项,你需要提出一种新方法来提取和排序{{ 1}}:
$scope.csTagGrp
数组创建一个包含所有csTags
数组的平面数组,即如下所示:
csTags
csTags
)更改为你拥有的([
{"keys": "1", "tags": "Quick Win"},
{"keys": "2", "tags": "follow up with respondent"},
// and so on from the first object
{"keys": "6", "tags": "Root cause"},
{"keys": "7", "tags": "Symptom"},
// and so on from the second object, and all the rest as well
]
)希望这有助于您前进!