Reputation: 505
I don't know how to clear a select-based filter, when limited to one property. This is the data:
$scope.items = [
{'name': 'Adam', 'fruit': 'apple'},
{'name': 'Shelley', 'fruit': 'apple'},
{'name': 'Barbara', 'fruit': 'plum'},
{'name': 'Steve', 'fruit': 'Adam\'s apple'},
{'name': 'Marty Appleton', 'fruit': 'onion'}
];
This is how I want to filter it, searching for the filter's text in item name
property:
<select ng-model="select1.name" ng-options="item.name as item.name for item in items">
<option value="">No filter</option>
</select>
<div ng-repeat="item in items | filter:select1">
{{ item.name }}: {{ item.fruit }}
</div>
When I select one of the options, the list is filtered as expected. But when after that I select the empty "No filter" option again, the list shown is empty. It works perfectly well if I don't limit the filter to one property, i.e. use ng-model="select1"
instead of ng-model="select1.name"
. It also works if I use a text input instead.
Here's a working example of this in action -- you'll notice that you cannot clear the filter with the bottom-right select, but you can with all other elements.
http://codepen.io/anon/pen/vLHqa
I'm lost. What am I doing wrong?
Upvotes: 3
Views: 5600
Reputation: 2049
The accepted answer will not work for situations where you need more than one select filter and will only work in a global way like any.
There is some quirky behaviour when you use ng-options with explicit options. I find that falling back to the simple ng-repeat will work better in some situations.
Instead you should do:
<select ng-model="select1.name">
<option value="" selected>No filter</option>
<option ng-repeat="item in items" ng-value="item.name">{{item.name}}</option>
</select>
Try it - I forked your CodePen
This way you could have two select filters selecting off two properties.
<select ng-model="select1.fruit">
<option value="" selected>No filter</option>
<option ng-repeat="item in items" ng-value="item.fruit">{{item.fruit}}</option>
</select>
Upvotes: 0
Reputation: 1097
The latest (unstable) versions of Angular introduce a hook for you to drop in a comparator function, which is where I'd LIKE to put what I'm about to show you. But, I'm stuck on v1.0.7, so I had to approach it with the below.
The issue is that even though the user selects an empty string when they select the "empty" option, the property on the object you're filtering against still exists, so Angular's $filter compares each elements' matching property to that empty string, instead of treating that property as removed.
So, I added an ng-change
event on my <select />
directive which would delete the property from my filter template object, thereby resetting the filter. Been working for me so far!
Example:
<!-- Assuming select1 is the filter template object, note the ng-change attribute added to your select element -->
<select ng-change="checkForClear( select1 )" ng-model="select1.name" ng-options="item.name as item.name for item in items" >
<option value="">No filter</option>
</select>
<div ng-repeat="item in items | filter:select1">
{{ item.name }}: {{ item.fruit }}
</div>
<!-- Then, in your controller -->
<script>
// Assuming your controller is set up...
$scope.checkForClear = function( filterTemplate ){
if( filterTemplate.name == null || filterTemplate.name === '' ){
delete filterTemplate.name; // <== THIS removes the property from the template filter and clears the filter for Angular
}
}
</script>
Upvotes: 0
Reputation: 399
Change to:
<select class="problem" ng-model="select1" ng-options="item.name for item in items">
It's will be work. http://codepen.io/anon/pen/qroJp
Upvotes: 3