Michael
Michael

Reputation: 13626

How to make angularjs filter work only once?

I have this filter:

filter:{ ClientId:details.client.Id }

Here how I use It:

  <uib-accordion-group ng-repeat="contract in details.contracts | filter:{ ClientId:details.client.Id } " is-open="false">
            <uib-accordion-heading>
                <div class="text-center">
                </div>
            </uib-accordion-heading>
            <div class="form-group">
                bla bla
            </div>
        </uib-accordion-group>
</uib-accordion>

How can I make filter work only once when uib-accordion derective is created?

Upvotes: 0

Views: 200

Answers (2)

jusopi
jusopi

Reputation: 6813

Per the documentation

When filters are executed

In templates, filters are only executed when their inputs have changed. This is more performant than executing a filter on each $digest as is the case with expressions.

There are two exceptions to this rule:

In general, this applies only to filters that take primitive values as inputs. Filters that receive Objects as input are executed on each $digest, as it would be too costly to track if the inputs have changed.

Filters that are marked as $stateful are also executed on each $digest. See Stateful filters for more information. Note that no Angular core filters are $stateful.

So in your case, so long as details.client.Id isn't triggered from some input's change event or isn't triggering a digest, your filter is running as performant as it can be.

Another way would be to call a controller method that has a cached value. It won't prevent the filter from firing, but it will immediately return a cached value. I don't recommend this though because angular filters are generally the prescribed solution for performant filtering solutions.

controller method

$scope.getCached = function(){
    if(cachedValue) return cachedValue
    return cachedValue = ...
}
    

implementation

<div ng-repeat="obj in objs | filter:getCached()">

Upvotes: 2

Petr Averyanov
Petr Averyanov

Reputation: 9486

You can use contract in ::details.contracts | filter:{ ClientId:details.client.Id }. This will evaluates whole expression once (ok, not once, until it becomes defined). But it also wont update expression when details.contracts changes.

Upvotes: 2

Related Questions