Ace Hyzer
Ace Hyzer

Reputation: 355

Unselecting ng-options dropdown in AngularJS

I've created a select dropdown using ng-options that is used to filter a list on the page.When the page loads, the dropdown is blank and no filtering has occurred.

on initial page load

When I select an option, filtering happens properly, but the blank option disappears, and thus I am forced to have a department-filtered version of the list unless I refresh the page and start over:

Before: Before Selecting, the blank option still there

After: Blank option gone

Here is my code:

.html file:

         Department:
        <select ng-model="search.SubDepartmentID" ng-options="d.SubDepartmentID as d.DepartmentLabel for d in DepartmentList"></select>
        
        <br />
        <div class="span10">
            <!--Body content-->

            <ul>
                <li ng-repeat="(index,e) in filteredEmployees | filter:search | orderBy:orderProp | startFrom:(currentPage - 1)*pageSize | limitTo:pageSize"
                    class="thumbnail employee-listing">
                    <a href="#/Employee/{{e.EmployeeID}}" class="thumb">
                        <img style="height: 100px; width: auto;" ng-src="../Images/CurrentEmployees/{{e.ImageName}}"></a>
                    <p><a href="#/Employee/{{e.EmployeeID}}">{{e.FullName}}</a></p>
                    <p>{{e.Department}}</p>
                </li>
            </ul>

I want to be able to return it to the blank option so that I have a completely unfiltered list. Doing a value="" option or just completely empty doesn't work, because it's filtering based on value, and nothing matches the empty value.

Any Help or direction would be much appreciated!

Upvotes: 5

Views: 9476

Answers (5)

Greg Michalec
Greg Michalec

Reputation: 849

Here's a solution that doesn't involve adding an extra $watch to your controller.

As has been suggested, the first step is to add an empty option to the select:

<select ng-model="typeFilter" ng-options="i.value as i.label for i in types">
  <option value=""></option>
</select>

However, if you are using this value as a filter, this won't work as expected, since (as pointed out by @GruffBunny), in angular 1.2+, empty selects are interpreted as null values, so the filter is searching for null vs not applying the filter.

I found a simple fix to this problem:

<div ng-repeat='item in items | filter:{type: typeFilter || undefined}'>
  {{item.name}} {{ item.type}}
</div>

That is, if the value of typeFilter is not truthy, set the filter value to undefined (i.e. don't apply the filter). Note that if 0 or false are valid filter values, you'll need to get a bit more nuanced. I haven't tested this, but something along these lines should work in that case:

 <div ng-repeat='item in items | filter:{type: typeFilter !== null ? typeFilter : undefined}'>
  {{item.name}} {{ item.type}}
</div>

Hopefully this saves someone some head-scratching :)

Upvotes: 0

Ace Hyzer
Ace Hyzer

Reputation: 355

Thanks everyone for the responses, I took a mix of a few of your responses, added in a watch and achieved what I wanted, here is what I ended up with:

<select ng-model="search.SubDepartmentID" ng-options="d.SubDepartmentID as d.DepartmentLabel for d in DepartmentList"><option value=""></option></select>

So I did add the empty value, but I modified the watch that I already had in my controller to set the $scope.search.SubDepartmentID to undefined if it comes back null:

$scope.$watchCollection('[search.$, search.Status, search.SubDepartmentID]', function (newSearch) {
    if ($scope.search != undefined) {
        if ($scope.search.SubDepartmentID == null) {
            $scope.search.SubDepartmentID = undefined;
        }
    }
});

The $scope.search.SubDepartmentID is undefined upon page load, and resetting it to undefined on select of the empty value did the trick!

Thanks again for all your help!

Upvotes: 9

Gruff Bunny
Gruff Bunny

Reputation: 27986

If you have complex filtering requirements you may be better off using a function as a filter.

Add an empty option to the select:

<select ng-model="...." ng-options="....">
    <option value=''>Choose a value</option>
</select>

Supply a function to the filter that should return true for all employees that should be shown:

<li ng-repeat="e in filteredEmployees | filter:filterEmployee>{{e.FullName}}</li> 

On the controller:

$scope.filterEmployee = function(employee) {
    return !search.SubDepartmentID || employee.SubDepartmentID == search.SubDepartmentID    
}

Upvotes: 1

aintnorest
aintnorest

Reputation: 1406

I'm not sure if the first answer works of a value=' ' since your question made it sound like you had tried that. I would set a value = to a function that deletes the variable used to filter. That way it re-instantiates and sets to undefined again.

Upvotes: 2

dcodesmith
dcodesmith

Reputation: 9614

You need to place a blank option in onload

<select ng-model="search.SubDepartmentID" ng-options="d.SubDepartmentID as d.DepartmentLabel for d in DepartmentList">
    <option value=''></option>
</select>

Upvotes: 3

Related Questions