Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm writing a custom Angular filter that randomly capitalizes the input passed to it.

Here's the code:

angular.module('textFilters', []).filter('goBananas', function() {
  return function(input) {

    var str = input;
    var strlen = str.length;

    while(strlen--) if(Math.round(Math.random())) {
      str = str.substr(0,strlen) + str.charAt(strlen).toUpperCase() + str.substr(strlen+1);
    }

    return str;
  };
});

I call it in my view like so:

    <a class='menu_button_news menu_button' ng-href='#/news'>
        {{"News" | goBananas}}
    </a>

It works, but in my console I'm seeing a rootScope:infdig (infinite digest) loop.

I'm having some trouble understanding why this is happening and what I can do to resolve it. If I understand correctly, this is due to the fact that there are more than 5 digest actions called by this function. But the input is only called once by the filter, right?

Any help appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.0k views
Welcome To Ask or Share your Answers For Others

1 Answer

The problem is that the filter will produce a new result every time it is called, and Angular will call it more than once to ensure that the value is done changing, which it never is. For example, if you use the uppercase filter on the word 'stuff' then the result is 'STUFF'. When Angular calls the filter again, the result is 'STUFF' again, so the digest cycle can end. Contrast that with a filter that returns Math.random(), for example.

The technical solution is to apply the transformation in the controller rather than in the view. However, I do prefer to transform data in the view with filters, even if the filter applies an unstable transformation (returns differently each time) like yours.

In most cases, an unstable filter can be fixed by memoizing the filter function. Underscore and lodash have a memoize function included. You would just wrap that around the filter function like this:

.filter('myFilter', function() {
  return _memoize(function(input) {
    // your filter logic
    return result;
  });
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...