Making an angular filter conditional

I’m currently using a text input to filter a list of items. I’d like to make it so when a particular variable is set, the list doesn’t filter, regardless of what the text input is. Any advice on how I can accomplish this?

<a ng-repeat="set in data | filter: { value: search }" data-id="{{set.id}}" ng-mousedown="setBox(set)" ng-mouseover="setSelected(set, $event)" ng-bind-html="set.value | trustHTML"></a>

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

You can achieve this if you set the filter expression to '' (or undefined) – this causes the filter not to be applied – for when your disableFilter is set, or to the actual filter expression otherwise.

EDIT 2:
The other answer (below by @Ryan) is simpler and easier to understand. Can’t remember now whether it didn’t work for me initially or I simply didn’t think of this simpler way.

So, assuming, this toggling variable – disableFilter – is a boolean :

<a ng-repeat="set in data | filter: (!disableFilter || '') && filterExpression">

(with filterExpression being whatever the expression you want to filter by). Your specific case would be:

<a ng-repeat="set in data | filter: (!disableFilter || '') && {value: search}">

EDIT:

To explain how the above works.

  1. Remember that || and && return the value of one of its operands.
  2. || and && use short-circuit evaluation – true || (anything) returns true; false && (anything) returns false – without evaluating the (anything) expression.
  3. '' is falsy (or use undefined instead, if it’s clearer)

And so,

when disableFilter === true, !disableFilter === false, thus the second operand of || – the empty string '' – is evaluated (it’s falsy), and (!disableFilter || '') returns '' – a falsy value, which short-circuits the && operation and does not evaluate the second operand of &&. The return value of the expression is thus ''.

when disableFilter === false, !disableFilter === true, which short-circuits the || operation, then the second operand of && is evaluated and returned. The return value of the expression is thus {value: search}.

Read more about logical operators here

Solution 2

I think the following is a slightly less tricky solution. Tricky solutions cause bugs for future developers.

Here’s my suggestion:

<a ng-repeat="set in data | filter: (shouldFilter ? filterExpression : '')">

or

<a ng-repeat="set in data | filter: (shouldFilter ? {value: search} : '')">

Simply, if shouldFilter, then give it your filter expression, otherwise give it nothing.
Using a simple ternary expression will be easier for readability.

Solution 3

Maybe use an ng-if?

<a ng-if="!myConditional" ng-repeat="set in data" data-id="{{set.id}}" ng-mousedown="setBox(set)" ng-mouseover="setSelected(set, $event)" ng-bind-html="set.value | trustHTML"></a>
<a ng-if="myConditional" ng-repeat="set in data | filter: { value: search }" data-id="{{set.id}}" ng-mousedown="setBox(set)" ng-mouseover="setSelected(set, $event)" ng-bind-html="set.value | trustHTML"></a>

That seems to be the solution.

Solution 4

Here is what I did. First, I had a select control, populated from my controller, with one static item (Select…) with a zero length string value:

<select data-ng-model="districtFilter" class="form-control" data-ng-options="d.DistrictId as d.DistrictName for d in districts | orderBy: 'DistrictName'"><option value="">Select...</option></select>

Then I applied the filter conditionally on the table. It appears when the filter is null, setting it to undefined clears it:

<tr data-ng-repeat="courtEntity in courts | filter:{ 'DistrictId' : districtFilter === null ? undefined : districtFilter}">

Solution 5

I had a complicated case

  • Have a list of records say it products
  • Filter by two other property prop1, prop2 selected by user from drop down
  • Another dropdown (prop3) have two value 1 and 2, if user select 2 filter should not be applied

Hers is my outcome:

ng-repeat="prod in filterdProd = 
 (products | filter : model.prop3 == 2 ? '' :  
   { 'prop1': model.prop1 || 'none', 
     'prop2': model.prop2 }) | 
  orderBy: 'productrName'"

if model.prop3 == 2 ? '' filter will not apply otherwise …

We can also use the count of records by using filterdProd

Solution 6

I found the following solution more easy and effective

angular.module('myApp', []).controller('namesCtrl', function($scope) {
    $scope.package=[{"PkgServiceId":null,"PkgServicesName":" HB, TLC, DLC &amp; ESR, EDTA WHOLE BLOOD, HBSAG CONFIRMATION,SERUM, Blood Cholesterol","PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":108,"ServiceName":"Family Health Package"},{"PkgServiceId":108,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":70,"ServiceName":"HB, TLC, DLC & ESR, EDTA WHOLE BLOOD"},{"PkgServiceId":108,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":71,"ServiceName":"HBSAG CONFIRMATION,SERUM"},{"PkgServiceId":108,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":3,"ServiceDesc":"Its used to evaluate your overall health and detect a wide range of disorders","ServiceId":2,"ServiceName":"Blood Cholesterol"},{"PkgServiceId":null,"PkgServicesName":" MRI Test, HB, TLC &amp; DLC, EDTA WHOLE BLOOD","PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":107,"ServiceName":"Child Health Package"},{"PkgServiceId":107,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":"Its used to evaluate your overall health and detect a wide range of disorders","ServiceId":5,"ServiceName":"MRI Test"},{"PkgServiceId":107,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":69,"ServiceName":"HB, TLC & DLC, EDTA WHOLE BLOOD"}] ;
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="namesCtrl">
<ul>
      <li ng-repeat="x in package">
        {{ x.ServiceName }}
        
      </li>
    </ul>
<p>Above is the total data set without filtering.</p>
<ul>
  <li ng-repeat="x in package| filter :{PkgServiceId: null}">
    {{ x.ServiceName }}
    {{ x.PkgServiceId }}
    
  </li>
</ul>

</div>



<p>This example displays only the packages containing the packageId "null".</p>

</body>
</html>

Solution 7

In HTML Template Binding

{{ dataX | date: expression ? 'dd/MM' : 'dd/MM/yyyy' }}

Solution 8

Make functions and combine with filterExpression.

Example I have a students list as below:

$scope.students = [  
   { name: 'Hai', age: 25, gender: 'boy' },  
   { name: 'Hai', age: 30, gender: 'girl' },  
   { name: 'Ho', age: 25, gender: 'boy' },  
   { name: 'Hoan', age: 40, gender: 'girl' },  
   { name: 'Hieu', age: 25, gender: 'boy' }  
 ];  

I want to filter students via gender to be boy and filter by name of them.

The first I create a function named “filterbyboy” as following:

$scope.filterbyboy = function (genderstr) {  
   if ((typeof $scope.search === 'undefined')||($scope.search === ''))  
     return (genderstr = "")  
   else  
    return (genderstr = "boy");  
 };  

Explaination: if not filter name then display all students else filter by input name and gender as ‘boy’

Here is a demo How to use and operator in AngularJs example

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply