Stéphane
Stéphane

Reputation: 442

How to disable an AngularJs filter when checkboxes are false (disabled)?

I have a question about how to disable a AngularJS filter related to checkboxes.

I have a classic construction:

The object:

 $scope.wines = [
    { "name": "Wine a", "type": "red", "country": "france", "style": "strong" },
    { "name": "Wine a", "type": "white", "country": "italie", "style": "medium" },
    { "name": "Wine a", "type": "white", "country": "france", "style": "light" },
    { "name": "Wine a", "type": "rose", "country": "usa", "style": "strong" },
    { "name": "Wine a", "type": "champagne", "country": "chili", "style": "medium" },
    { "name": "Wine a", "type": "red", "country": "brazil", "style": "strong" },
    { "name": "Wine a", "type": "red", "country": "france", "style": "strong" }
  ];
  $scope.winetypes = {red : true,white : true,rose : true, champagne : true};

This filter is used to display only the related choice made with the checkboxes:

app.filter('winetypefilter', function () {
  return function(input, filter) {
    var result = [];
    angular.forEach(input, function (wine) {
        angular.forEach(filter, function (isfiltered, type) {
            if (isfiltered && type === wine.type) {
                result.push(wine);
            }
        });
    });
    return result;
  };

The results are displayed with this html code:

<li ng-repeat="(type, value) in winetypes">
  <input type="checkbox" ng-model="winetypes[type]" /> {{type}}
</li>

<ul>
  <li ng-repeat="wine in wines | winetypefilter:winetypes">
    {{wine.name}} is a {{wine.type}} with {{wine.style}} style from {{wine.country}}
  </li>
</ul>

Here the demo: http://plnkr.co/edit/nIQ2lkiJJY9MwJKHrqOk?p=preview

Upvotes: 0

Views: 2458

Answers (3)

m.e.conroy
m.e.conroy

Reputation: 3538

http://plnkr.co/edit/w4aCjOW5UnnFQcAKYBT9?p=preview

app.filter('winetypefilter', function () {
  return function(input, filter) {
    var result = [];
    var alt = [];
    var flag = false;
    angular.forEach(input, function (wine) {
        flag = false;
        angular.forEach(filter, function (isfiltered, type) {
            if (isfiltered && type === wine.type) {
                result.push(wine);
                flag = true;
            }
        });
        if(!flag)
          alt.push(wine);
    });
    if(!angular.equals(result.length,0))
      return result;
    else
      return alt;
  };
});

As per one of the other comments, you can forgo the extra forEach Updated Plunker: http://plnkr.co/edit/w4aCjOW5UnnFQcAKYBT9?p=preview

app.filter('winetypefilter', function () {
  return function(input, filter) {
    var result = [];
    var alt = [];
    angular.forEach(input, function (wine) {
        if(filter[wine.type])
          result.push(wine);
        else
          alt.push(wine);
    });
    if(!angular.equals(result.length,0))
      return result;
    else
      return alt;
  };
});

Upvotes: 1

ryeballar
ryeballar

Reputation: 30088

You can actually tweak your custom filter, winetypefilter, to check if all winetypes boolean values are disabled. if all values are disabled, then simply return the original array, in this case input, otherwise continue with your original filter.

Note: I also changed the way you filtered the winetypes, the extra layer of forEach wasn't necessary to determine if filtering should take place. just check if wine.type of filter was true in the winetypes json

Forked Plunker

e.g.

app.filter('winetypefilter', function () {
  return function(input, filter) {
    var result;

    if(canFilter(filter)) {
      result = [];
      angular.forEach(input, function(wine) {
        if(filter[wine.type])
          result.push(wine);
      });
    } else
      result = input;

    return result;
  };

  function canFilter(filter) {
    var hasFilter = false;
    angular.forEach(filter, function(isFiltered) {
      hasFilter = hasFilter || isFiltered;
    });
    return hasFilter;
  }
});

Upvotes: 1

Srinath Mandava
Srinath Mandava

Reputation: 3462

I used ng-if to show depending on whether all the checkboxes are checked...

    <ul>
      <li ng-if="check()" ng-repeat="wine in wines | winetypefilter:winetypes">
        {{wine.name}} is a {{wine.type}} with {{wine.style}} style from {{wine.country}}
      </li>
      <li ng-if="!check()" ng-repeat="wine in wines ">
        {{wine.name}} is a {{wine.type}} with {{wine.style}} style from {{wine.country}}
      </li>
    </ul>

and the controller code..

  $scope.check=function()
  {
    if($scope.winetypes.red===false&&$scope.winetypes.white===false&&$scope.winetypes.rose===false&&$scope.winetypes.champagne===false)
    {
      return false;
    }
    return true;
  };

http://plnkr.co/edit/MWL727Yfq8MLWodmaBDk?p=preview

Upvotes: 1

Related Questions