Omid Shariati
Omid Shariati

Reputation: 1916

How to make angular js hide DOM elements, and not remove them, in filters

Angular ng-repeat with filter works this way (I just discovered it by observing DOM in Chrome's developer tools):

It actually removes the nodes which don't satisfy filter condition and re-renders everything.

See this fiddle example. If you look at the DOM, and see what happens there, you can understand what I mean.

<div ng-app>
  <h2>Instant Search</h2>
  <div ng-controller="SearchCtrl">
    <input type="text" ng-model="filterText" />
    <ul>
      <li ng-repeat="state in states | filter:filterText">
        <label>
            <input type="checkbox" ng-model="state.abbreviation">
            {{state.name}}
        </label>
      </li>
    </ul>
  </div>
</div>

What I need now, is to make angular js hide nodes, not remove them. In other words, when I filter nodes, for example I want to make those nodes which don't satisfy filter condition to have a class of hidden, and I'll hide them via CSS.

Upvotes: 2

Views: 7363

Answers (5)

Franc
Franc

Reputation: 5496

Just replace filter with:

ng-show="([state] | filter:filterText).length > 0"

Upvotes: 0

Omid Shariati
Omid Shariati

Reputation: 1916

I thinks that one answer would be like this

<div ng-app>
  <h2>Instance Search</h2>
  <div ng-controller="SearchCtrl">
    <input type="text" ng-model="filterText" />
    <ul>
      <li ng-repeat="state in states" 
          ng-show="state.name.tolowerCase().indexOf(filterText.toLowerCase()) != -1">
        <label>
            <input type="checkbox" ng-model="state.selected">
            {{state.name}}
        </label>
      </li>
    </ul>
  </div>
</div>

Upvotes: 1

Nathaniel Johnson
Nathaniel Johnson

Reputation: 4849

ng-show placed on the repeating element will cause them to be hidden: Fiddle http://jsfiddle.net/NAumK/19/

http://docs.angularjs.org/api/ng.directive:ngShow

<div ng-app>
  <h2>Todo</h2>
  <div ng-controller="TodoCtrl">
    <input type="text" ng-model="filterText" />
    <ul>
      <li ng-repeat="state in states" ng-show="state.name.indexOf(filterText) != -1">
        <label>
            <input type="checkbox" ng-model="state.abbreviation">
            {{state.name}}
        </label>
      </li>
    </ul>
    <input type="text" ng-model="textFilter" />
  </div>
</div>

Filters remove elements as does the ng-if and ng-switch directives. You can also use css coupled with the ng-class directive to hide the elements however I recommend sticking with the ng-show for clarity. One further note of caution, hiding as opposed to removing elements makes the test cases harder to prove. You can have collisions with classes that display incorrectly but still pass (Selenium) tests.

Upvotes: 4

Sergiu Paraschiv
Sergiu Paraschiv

Reputation: 10163

You cannot use filter in ng-repeat because it filters the actual array that ng-repeat receives. You'll have to implement your own "filtering" logic.

I'd do it using a conditional ng-class, like this:

<li ng-repeat="state in states" ng-class="{'hidden': isHidden(state)}">
    <label>
        <input type="checkbox" ng-model="state.abbreviation">
        {{state.name}}
    </label>
</li>

$scope.isHidden = function(state) {
    if(state.name.toLowerCase().indexOf($scope.filterText.toLowerCase()) < 0) {
        return true;
    }

    return false;
}

Upvotes: 1

HasanAboShally
HasanAboShally

Reputation: 18685

You can use ng-show or ng-hide instead of filters.

Upvotes: 1

Related Questions