Как использовать флажок для фильтрации результатов с помощью Angular?

Я пытаюсь применить фильтр, используя флажки.

Флажки отображаются правильно:

<div data-ng-repeat="cust in customers">
    <input type="checkbox" data-ng-model="search.city" data-ng-true-value="{{ cust.city }}" data-ng-false-value=""/> {{ cust.city }}
</div>

но при установке любого флажка ничего не происходит:

<table>

    <!-- table heading goes here -->

    <tbody>
        <tr data-ng-repeat="customer in customers | filter : search">
            <td >
                {{ customer.firstName }}
            </td>
            <td >
                {{ customer.lastName }}
            </td>
            <td >
                {{ customer.address }}
            </td>
            <td >
                {{ customer.city }}
            </td>
        </tr>
    </tbody>
</table>

В таблице показаны все клиенты.

Чего я хочу добиться, так это: когда один или несколько флажков отмечены, в таблице должны отображаться только те строки, которые соответствуют условию отмеченных флажков.

Что мне нужно сделать, чтобы это заработало?


person Martijn    schedule 12.05.2013    source источник


Ответы (2)


Похоже, вы предоставляете список клиентов, а когда выбран один или несколько, отображаете таблицу клиентов, которые находятся в том же городе, что и выбранные клиенты.

Для этого вам понадобится пользовательский фильтр:

// Define our filter
app.filter('selectedCustomerCities', function($filter) {
  return function(customers) {
    var i, len;

    // get customers that have been checked
    var checkedCustomers = $filter('filter')(customers, {checked: true});

    // Add in a check to see if any customers were selected. If none, return 
    // them all without filters
    if(checkedCustomers.length == 0) {
      return customers;
    }

    // get all the unique cities that come from these checked customers
    var cities = {};
    for(i = 0, len = checkedCustomers.length; i < len; ++i) {
      // if this checked customers cities isn't already in the cities object 
      // add it
      if(!cities.hasOwnProperty(checkedCustomers[i].city)) {
        cities[checkedCustomers[i].city] = true;
      }
    }

    // Now that we have the cities that come from the checked customers, we can
    //get all customers from those cities and return them
    var ret = [];
    for(i = 0, len = customers.length; i < len; ++i) {
      // If this customer's city exists in the cities object, add it to the 
      // return array
      if(cities[customers[i].city]) {
        ret.push(customers[i]);
      } 
    }

    // we have our result!
    return ret;
  };
});

Затем ваша разметка изменится на что-то вроде этого:

<div data-ng-repeat="customer in customers">
  <!-- record that this customer has been selected -->
  <input type="checkbox" ng-checked="customer.checked" ng-model="customer.checked" /> {{ customer.city }}
</div>

<table>
  <!-- table heading goes here -->
  <tbody>
      <!-- use our custom filter to only display customers from the cities selected -->
      <tr data-ng-repeat="customer in customers | selectedCustomerCities">
          <td>{{ customer.firstName }}</td>
          <td>{{ customer.lastName }}</td>
          <td>{{ customer.address }}</td>
          <td>{{ customer.city }}</td>
      </tr>
  </tbody>
</table>

Вы можете увидеть, как это работает на этом плункере: http://plnkr.co/edit/GlHRLKECR4jeBS7Vf7TX?p=preview

person Jay    schedule 12.05.2013
comment
Это почти то, что я хочу. По умолчанию отображаются все клиенты. Когда для определенного города (или городов) установлен флажок, фильтр применяется. - person Martijn; 12.05.2013
comment
Я обновил свой ответ. Изменение было тривиальным: if(checkedCustomers.length == 0) { return customers; } фактически возвращались все клиенты, если ни один из них не был проверен. Надеюсь, все это имеет для вас смысл, и дайте мне знать, если вам нужно что-то объяснить. - person Jay; 13.05.2013
comment
Это именно то, что я хочу. Я понимаю почти все, кроме этого $filter('filter')(customers, {checked: true}); Не могли бы вы объяснить это немного подробнее? - person Martijn; 13.05.2013
comment
В AnguarJS вы можете использовать службу $filter либо в шаблонах HTML, либо в самом JavaScript. AngularJS предоставляет набор фильтров, таких как currency, нижний регистр и т. д. для удобства. Они также предоставляют фильтр filter, который я использую здесь в JavaScript. . Прочтите документацию по сервису фильтров + предоставляемый фильтр filter для получения дополнительной информации. - person Jay; 13.05.2013
comment
чтобы избежать ошибки cannot read property 'length' of undefined, если ваши данные поступают из веб-API, вы должны проверить if (!angular.isUndefined(customers)) - person Ravimallya; 13.10.2016

Вы можете передать функцию фильтру AngularJS. Например:

Установите входной тег как:

<input type="checkbox" ng-model="search[cust.city]" /> {{ cust.city }}

Установите фильтр как:

<tr data-ng-repeat="customer in customers | filter:searchBy() ">

В вашем контроллере:

function ctrl($scope) {
  $scope.customers = [...];

  $scope.search = {};    
  $scope.searchBy = function () {
    return function (customer) {
      if ( $scope.search[customer.city] === true ) {
        return true;
      }
    }
  };
}

Если вы хотите показать всех клиентов при запуске, просто инициализируйте $scope.search с помощью city из массива customers.

Вот пример плунжера.

person marcoseu    schedule 12.05.2013
comment
Этот ответ мне нравится намного больше. Похоже, что это было бы быстрее, а также. - person fauverism; 17.12.2014
comment
Если вы хотите показать всех клиентов при запуске, просто инициализируйте $scope.search с городом из массива клиентов. Не могли бы вы объяснить это немного подробнее. любой пример для этого ?? - person Neeraj Sharma; 25.08.2016
comment
Это решение не группирует флажки, если 2 или более клиентов принадлежат к одному городу. - person llermaly; 22.12.2016