Making an angular filter conditional
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}">
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.
- Remember that
||
and&&
return the value of one of its operands. ||
and&&
use short-circuit evaluation -true || (anything)
returnstrue
;false && (anything)
returnsfalse
- without evaluating the(anything)
expression.''
is falsy (or useundefined
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
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.
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.