Making an angular filter conditional

Angularjs

Angularjs Problem Overview


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>

Angularjs Solutions


Solution 1 - Angularjs

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

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

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

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

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

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

In HTML Template Binding

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

Solution 8 - Angularjs

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRohitView Question on Stackoverflow
Solution 1 - AngularjsNew DevView Answer on Stackoverflow
Solution 2 - AngularjsRyanView Answer on Stackoverflow
Solution 3 - AngularjsAaronView Answer on Stackoverflow
Solution 4 - AngularjssteveareenoView Answer on Stackoverflow
Solution 5 - AngularjsAli AdraviView Answer on Stackoverflow
Solution 6 - AngularjsProjesh PalView Answer on Stackoverflow
Solution 7 - AngularjsAugusto SaviView Answer on Stackoverflow
Solution 8 - AngularjsLewis HaiView Answer on Stackoverflow