Matt G. Matt G. - 1 year ago 66
AngularJS Question

Custom filter works initially, but not after a Search is performed

I have an issue with a custom filter that I'm trying to figure out. I have configured a jsFiddle to replicate the issue.

The Out of Stock filter is the custom filter with the odd behavior. Initially it works fine. However, if you enter text into the search box, remove the text from the search box, and then try to use the Out of Stock filter again it returns no results.

I'm stumped. I think that this may have to do with the way the filter logic is working in the controller, but I'm not understanding why it is not reading the item quantity value after text is entered into the search.

Here is the custom filter logic for the 'Out of Stock' filter:

$scope.changeStockFilter = function() { // this function call on change checkbox value
if ($scope.searchInventory.qty === 0) {
$scope.exactMatching = true; // if qty 0 then set true
} else {
$scope.exactMatching = false;

Here is how the filter function is being called

<div class="checkbox">
<input type="checkbox" name="filter" ng-model="searchInventory.inventory" data-ng-true-value="0" data-ng-false-value="''" ng-change="changeStockFilter()">
Out of Stock

This is how the filter is being applied to the ngrepeat

<div ng-repeat="item in inventory | filter: searchInventory : exactMatching | orderBy:sortOrder as filtered_result track by $index">

I also considered that maybe there was an issue with 'track by' in the filter, assuming I was using it incorrectly. I read a few pages linked below and I don't think that is the issue here. I could be wrong, of course.

I would appreciate any guidance on this issue. Thank you!!!

Answer Source

After using the search your filter object looks like this:

{ "qty": 0, "$": "" }

along with exactMatching = true this returns no results since angular uses the strict comparison in this case (angular.equals(actual, expected)) instead of case-insensitive substring match and it does not find anything due to this part "$": "" (which means there should be at least one property equal to empty string).

You should use a separate filter for outOfStock thing with a strict comparison. The other filters should use the substring match in case insensitive way:

<div ng-repeat="item in inventory | filter: searchInventory | filter : outOfStockFilter | orderBy:sortOrder as filtered_result track by $index">

The filter function:

$scope.outOfStockFilter = function(value, index, array) {
    return $scope.searchQty != 0 || value.qty === 0;

Here the working fork:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download