过滤结果更改后,ng-show不会重新评估

时间:2018-01-18 20:04:18

标签: javascript angularjs

我在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;
&#13;
&#13;

1 个答案:

答案 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中的默认值。