4

I am trying to apply a filter using checkboxes.

The checkboxes are shown correctly:

<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>

but when checking any checkbox, nothing happens:

<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>

The table shows all the customers.

What I want to achieve is: when one or more checkboxes are checked, the table has to show only these rows which match the condition of the checked checkboxes.

What do I have to do to get this working?

2 Answers 2

7

You can pass a function to the AngularJS filter. For example:

Set you input tag as:

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

Set your filter as:

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

In your controller:

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

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

If you wish to show all customer at startup, simply initialise $scope.search with city from the customers array.

Here is a sample Plunker.

Sign up to request clarification or add additional context in comments.

3 Comments

I like this answer much better. It appears that it would be faster as well.
"If you wish to show all customer at startup, simply initialise $scope.search with city from the customers array. " Can you please explain this a bit more. any example for this ??
This solution does not group checkboxes if 2 or more customers belongs to the same city
3

It looks like you are providing a list of customers, and when one or more is selected, display a table of customers that are in the same city as those customers that are selected.

To do this, you will need a custom filter:

// 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;
  };
});

Your markup will then change into something like this:

<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>

You can see it working at this Plunker: http://plnkr.co/edit/GlHRLKECR4jeBS7Vf7TX?p=preview

5 Comments

This is almost what I want. By default all the customers are displayed. When a checkbox is checked for a certain city (or cities), the filter is applied.
I've updated my answer. The change was trivial: if(checkedCustomers.length == 0) { return customers; } basically returning all the customers if none were checked. Hopefully that all makes sense to you & let me know if you need anything explained.
That's exactly what I want. I understand almost everyhtinh, except this $filter('filter')(customers, {checked: true}); Could you explain this a little bit more?
In AnguarJS, you can use the $filter service in either the HTML Templates, or in the JavaScript itself. AngularJS provides a set of filters themselves such as currency, lowercase, etc for conveinence sake. They also provide the filter "filter" which is what I am using here in the JavaScript. Read the documentation for the filter service + provided filter "filter" for more information.
to avoid cannot read property 'length' of undefined error if your data is coming from web api, you've to check if (!angular.isUndefined(customers))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.