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>

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.