我在AngularJS中有一个循环,它使用文本输入过滤数组结果。过滤器效果很好;列表会立即在文本输入上更新。但是,如果您开始在输入中键入文本值,然后(使用退格键)删除您的条目,则会出现错误,其中alpha标题会重复。
例如,在提供的MCVE类型中""然后删除2个字母以留下空文本输入(并呈现完整列表)。您将看到重复的alpha标题:" A"," B"," C"等
为什么ng-show
用于显示标题,而不是在ng-repeat
过滤结果发生变化时重新评估?我该如何解决?
var app = angular.module('countriesApp',[]);
app.controller('countriesCtrl', ['$scope', '$http', function($scope, $http) {
$scope.countriesJSON = [
['Afghanistan','Zone3','A'],['Albania','Zone3','A'],['Algeria','Zone2','A'],['Angola','Zone2','A'],['Antigua','Zone2','A'],['Argentina','Zone2','A'],['Armenia','Zone3','A'],['Azerbaijan','Zone2','A'],['Bangladesh','Zone3','B'],['Belarus','Zone2','B'],['Belize','Zone3','B'],['Benin','Zone3','B'],['Bhutan','Zone3','B'],['Bolivia','Zone3','B'],['Bosnia','Zone2','B'],['Botswana','Zone2','B'],['Brazil','Zone2','B'],['Bulgaria','Zone2','B'],['Burkina Faso','Zone3','B'],['Burundi','Zone3','B'],['C African Rp','Zone3','C'],['Cambodia','Zone3','C'],['Cameroon','Zone3','C'],['Cape Verde','Zone3','C'],['Chad','Zone3','C'],['Chile','Zone2','C'],['China','Zone3','C'],['Colombia','Zone2','C'],['Comoros','Zone3','C'],['Congo','Zone3','C'],['Cook Islands','Zone2','C'],['Costa Rica','Zone2','C'],['Cote DIvoire','Zone3','C'],['Cuba','Zone2','C'],['Djibouti','Zone3','D'],['Dominica','Zone2','D'],['Dominican Republic','Zone2','D'],['Ecuador','Zone2','E'],['Egypt','Zone3','E'],['El Salvador','Zone3','E'],['Eritrea','Zone3','E'],['Ethiopia','Zone3','E'],['Federal State of Micronesia','Zone3','F'],['Fiji','Zone3','F'],['French Guiana','Zone2','F']
];
$scope.alphaHeader = function(curAlpha) {
showHeader = (curAlpha != $scope.alpha);
$scope.alpha = curAlpha;
return showHeader;
}
}]);
/* --------------------------------------------------------------- *
* search countries *
* ---------------------------------------------------------------- */
app.filter('search_countries', function() {
return function(input, query) {
// return all countries if nothing in query box
if (!query) return input;
//split query terms by space character
var terms = query.split(' ');
var output = [];
// iterate through input array
input.forEach(function(country){
var found = false;
passTest = true;
// iterate through terms found in query box
terms.forEach(function(term){
// if all terms are found set boolean to true
found = (country[0].toLowerCase().indexOf(term.toLowerCase()) > -1);
passTest = passTest && found;
});
// Add country to output array only if passTest is true -- all search terms were found in product
if (passTest) { output.push(country); }
});
return output;
}
});

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="countriesApp" id="countriesApp" style="padding-bottom: 30px;">
<div ng-controller="countriesCtrl">
<!-- Search Countries -->
<div class="form-group row">
<label for="search" class="col-sm-12 col-md-5 col-lg-4 control-label">Select the country you reside in.</label>
<div class="col-sm-8 col-md-7 col-lg-5">
<input id="search" type="text" ng-model="search_input" placeholder="Search Countries" class="form-control" autocomplete='off' />
</div>
</div>
<div class="col-xs-12 col-sm-12"><hr></div>
<!-- Countries list -->
<div class="row">
<div class="" ng-repeat="country in results = (countriesJSON | search_countries: search_input)">
<div ng-show="alphaHeader(country[2])" class="col-xs-12"><h3>{{ country[2] }}</h3></div>
<div class="col-xs-6 col-sm-6 col-md-4 col-lg-3">
<a ng-href="country.html?zone={{ country[1] }}&country={{ country[0] }}">
{{ country[0] }}
</a>
</div>
</div>
</div>
</div>
</div>
&#13;
答案 0 :(得分:1)
只需将track by $index
添加到ng-repeat
。
<div class="" ng-repeat="country in results = (countriesJSON | search_countries: search_input) track by $index">
var app = angular.module('countriesApp',[]);
app.controller('countriesCtrl', ['$scope', '$http', function($scope, $http) {
$scope.countriesJSON = [
['Afghanistan','Zone3','A'],['Albania','Zone3','A'],['Algeria','Zone2','A'],['Angola','Zone2','A'],['Antigua','Zone2','A'],['Argentina','Zone2','A'],['Armenia','Zone3','A'],['Azerbaijan','Zone2','A'],['Bangladesh','Zone3','B'],['Belarus','Zone2','B'],['Belize','Zone3','B'],['Benin','Zone3','B'],['Bhutan','Zone3','B'],['Bolivia','Zone3','B'],['Bosnia','Zone2','B'],['Botswana','Zone2','B'],['Brazil','Zone2','B'],['Bulgaria','Zone2','B'],['Burkina Faso','Zone3','B'],['Burundi','Zone3','B'],['C African Rp','Zone3','C'],['Cambodia','Zone3','C'],['Cameroon','Zone3','C'],['Cape Verde','Zone3','C'],['Chad','Zone3','C'],['Chile','Zone2','C'],['China','Zone3','C'],['Colombia','Zone2','C'],['Comoros','Zone3','C'],['Congo','Zone3','C'],['Cook Islands','Zone2','C'],['Costa Rica','Zone2','C'],['Cote DIvoire','Zone3','C'],['Cuba','Zone2','C'],['Djibouti','Zone3','D'],['Dominica','Zone2','D'],['Dominican Republic','Zone2','D'],['Ecuador','Zone2','E'],['Egypt','Zone3','E'],['El Salvador','Zone3','E'],['Eritrea','Zone3','E'],['Ethiopia','Zone3','E'],['Federal State of Micronesia','Zone3','F'],['Fiji','Zone3','F'],['French Guiana','Zone2','F']
];
$scope.alphaHeader = function(curAlpha) {
showHeader = (curAlpha != $scope.alpha);
$scope.alpha = curAlpha;
return showHeader;
}
}]);
/* --------------------------------------------------------------- *
* search countries *
* ---------------------------------------------------------------- */
app.filter('search_countries', function() {
return function(input, query) {
// return all countries if nothing in query box
if (!query) return input;
//split query terms by space character
var terms = query.split(' ');
var output = [];
// iterate through input array
input.forEach(function(country){
var found = false;
passTest = true;
// iterate through terms found in query box
terms.forEach(function(term){
// if all terms are found set boolean to true
found = (country[0].toLowerCase().indexOf(term.toLowerCase()) > -1);
passTest = passTest && found;
});
// Add country to output array only if passTest is true -- all search terms were found in product
if (passTest) { output.push(country); }
});
return output;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="countriesApp" id="countriesApp" style="padding-bottom: 30px;">
<div ng-controller="countriesCtrl">
<!-- Search Countries -->
<div class="form-group row">
<label for="search" class="col-sm-12 col-md-5 col-lg-4 control-label">Select the country you reside in.</label>
<div class="col-sm-8 col-md-7 col-lg-5">
<input id="search" type="text" ng-model="search_input" placeholder="Search Countries" class="form-control" autocomplete='off' />
</div>
</div>
<div class="col-xs-12 col-sm-12"><hr></div>
<!-- Countries list -->
<div class="row">
<div class="" ng-repeat="country in results = (countriesJSON | search_countries: search_input) track by $index">
<div ng-show="alphaHeader(country[2])" class="col-xs-12"><h3>{{ country[2] }}</h3></div>
<div class="col-xs-6 col-sm-6 col-md-4 col-lg-3">
<a ng-href="country.html?zone={{ country[1] }}&country={{ country[0] }}">
{{ country[0] }}
</a>
</div>
</div>
</div>
</div>
</div>
一旦我在ng-repeat
的背景下看到“复制”这个词,我实际上只是预感到了。
我想因为不同国家的区域(在国家/地区数组中)可能相同,因此内容跟踪是不安全的,这是AngularJS ng-repeat
中的默认值。