Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular filter doesn't update when service property changes

Perhaps this is a fundamental misunderstanding of Angular scope, but here goes.

I have a service that handles changing a language preference:

languageService.js

function languageService() {
  var language = "en";

  var service = {
    getLanguage: getLanguage,
    setLanguage: setLanguage

  };

  function getLanguage () {
    return language;
  }

  function setLanguage (newLang) {
   language = newLang;
  }

  return service;
}

I also have a filter that formats something:

someFilter.js

function myFilter(languageService) {
  return function(num) {
    var french = languageService.getLanguage() === 'fr';

    if (french) {
      return "is french!"
    } else {
      return "is other."
    }
  }      
}

I try to use this filter in some HTML: Blah blah {{ 'test' | someFilter }}.

It works, but only on load; if I call setLanguage('en'), the binding doesn't change.

like image 707
opticon Avatar asked Mar 15 '16 17:03

opticon


1 Answers

There are actually two issues with your code.

First, in the service you should fire a digest when your var changes. So it would be

myApp.factory('languageService', ['$rootScope', function ($rootScope) {
  var language = "en";

  var service = {
    getLanguage: getLanguage,
    setLanguage: setLanguage

  };

  function getLanguage () {
    return language;
  }

  function setLanguage (newLang) {
   language = newLang;
   $rootScope.digest();
  }

  return service;
}]);

Second and more subtle one. In angular, filters get updated only if the value you pass them in the markup changes (in your case is 'test'), for any other change to the scope your filter will be completely ignored.

The solution is to force angular to parse that particular filter on any digest.

myApp.filter('someFilter', ['localeService', function (localeService) {
  function filter (value) {
    var french = languageService.getLanguage === 'fr';

    if (french) {
      return "is french!"
    } else {
      return "is other."
    }
  }

  filter.$stateful = true; // This line does the trick

  return filter;
}]);

You can get more info on the Angular Docs

like image 155
L. Catallo Avatar answered Oct 24 '22 10:10

L. Catallo