Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - how to trigger filter on ng-click

I'm trying to make simple multi-language website. I have a small controller just to be able to change current language in root scope:

   app.controller('Ctrl', function($scope, $rootScope) {
       $rootScope.currentLang = 'en_US';
       $scope.switchLang = function(){
            if($rootScope.currentLang ==='en_US'){
                $rootScope.currentLang = 'cs_CS';
            } else {
                $rootScope.currentLang = 'en_US';
            }
        }
    });

And I want to store my data in filter:

   app.filter('ci18n', function($rootScope){
       return function(id_text){
           var translations = {
               'en_US' : {
                   'GREETING' : 'Hi'
               },
               'cs_CS' : {
                   'GREETING' : 'Cau'  
               }
            };

            return translations[$rootScope.currentLang][id_text];
        };
    });

Problem is that my website does't change with rootScope change. I need an idea how to solve it better or how to trigger filter again to change my texts.

Here is how I use the filter

<p>greet: {{'GREETING' | ci18n}}</p>
like image 485
Jan Omacka Avatar asked Dec 09 '22 02:12

Jan Omacka


1 Answers

Starting from Angular 1.3, filters are assumed to be stateless in order to speed things up in the common case. That means Anguar won't re-evaluate your filter if its input has not changed. Angular has no idea that you're also reading $rootScope.currentLang within the filter implementation, so it doesn't know that the filter needs to be re-evaluated if currentLang changes.

The solution is to mark your filter as stateful explicitly:

    app.filter('ci18n', function($rootScope){
       var filter = function(id_text){
           var translations = {
               'en_US' : {
                   'GREETING' : 'Hi'
               },
               'cs_CS' : {
                   'GREETING' : 'Cau'  
               }
            };

            return translations[$rootScope.currentLang][id_text];
        };

        filter.$stateful = true; // <-- the magic line

        return filter;
    });

Of course this does come with a performance penalty, but since your filter is just a map lookup, that shouldn't have much of an impact.

like image 164
Thomas Avatar answered Dec 14 '22 23:12

Thomas