Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Not all AngularJS filters are $locale aware after lang+locale changed #9159

Closed
dragosrususv opened this issue Sep 18, 2014 · 8 comments
Closed

Comments

@dragosrususv
Copy link

AFFECTS: All AngularJS versions, including latest master.
REPRODUCEABLE: Always, any browser or OS

PREREQUISITES
Everybody is aware of the AngularJS applications start phases, in particular the config phase which allows developers to load/decorate/prepare different items.
Still, there is a real need in AngularJS to lazy load stuff (modules, ctrls, locale, *).

BUG/PROBLEM INSIDE ANGULARJS
AngularJS filters are using the $locale in order to format different types of data: numbers, currencies, dates, date times, etc. The problem is that some of these filters have locally cached versions of the $locale and do not take the latest updated $locale service.

  1. Number filter - https://github.com/angular/angular.js/blob/master/src/ng/filter/filters.js#L118
  2. Currency filter - https://github.com/angular/angular.js/blob/master/src/ng/filter/filters.js#L53
    (others might as well have this problem)

POSSIBLE SOLUTION
All the filters should be $locale aware, as the date filter for instance ( https://github.com/angular/angular.js/blob/master/src/ng/filter/filters.js#L444 ). This one doesn't cache the $locale.{WHATEVER} and it works great.

.. AND THE CODE
Move the " var formats = $locale.NUMBER_FORMATS;" inside the returned function:

    function numberFilter($locale) {
      return function(number, fractionSize) {
        var formats = $locale.NUMBER_FORMATS;
        return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
          fractionSize);
      };
    }

REAL USE CASE:
We have an AngularJS application (which will go in production in a few weeks FYI) which requires loading of i18n look&feel on the fly (based on the language + culture combination). So if the user changes his lang_locale or just logs in with another account in the app, we would load the user lang_locale and rely on AngularJS for the number/currency/dates formatting.

ACTUAL IMPLEMENTATION
We decorated the $locale service and created a "setLocale" method which allows changing the $locale properties after the config phase of the app.

NOTE: Another title for this bug could have been: "Dynamically loading $locale files without refreshing the whole page"

@dragosrususv
Copy link
Author

@btford : please read my comment inside the pull request . if this is not a good fix, perf wise, then what is the angularjs suggestion for this use-case?

@btford
Copy link
Contributor

btford commented Sep 18, 2014

If you don't care about perf, you can override that filter with your own implementation fairly easily.

@lgalfaso
Copy link
Contributor

@dragosrususv there are several ways that this can be done without any change in the core, look at any external module that does this and it is fairly easy. E.g. https://github.com/lgalfaso/angular-dynamic-locale

@dragosrususv
Copy link
Author

@btford : unfortunately, the app does care about perf. is it mandatory to be a trade-off for the dynamic locale?

@lgalfaso : thank you for the reference. I'll take a look to see how you did it.

I still believe the presented scenario is normal and should be supported by default by AngularJS.

@dragosrususv
Copy link
Author

Finally, are we able to achieve this in any way? Because manually copy-pasting 'number' filter functionality from angularjs into our own app seems like a brutish way of doing things.

At some point there was a commit implementing some $stateful functionality for filters, like:

$provide.decorator("currencyFilter", function($delegate) {
  $delegate.$stateful = true;
  return $delegate;
});

Was that merged finally, is that planned in any way?

@michellebionico
Copy link

I've had the same problem!!
@dragosrususv thank you for the issue, it was my last resort!!!
I share the same opinion, i think this problem should be addressed and resolved in the next release of angular JS!!!

For now, i'm rewriting the number and currency functions on my app!!

Hope this problem is solved soon, because thats a pretty bad kludge

I've made my solution available in GitHub, in case someone doesn't feel like rewriting tha functions by himself:
https://github.com/michellebionico/i18n-with-Angular-JS

@dragosrususv
Copy link
Author

@btford : I guess we can close this, as "stateful" state may be overriden - @caitp provided an example in one of the PR's: http://plnkr.co/edit/qvzXkQkVtTLHvHVYXTdU?p=preview - seems to be the correct way to proceed.

@GeBeater
Copy link

@dragosrususv
I created a decorator for $locale which has references to the affected "useLocale, DATETIME_FORMATS, NUMBER_FORMATS, id, pluralCat" properties of the selected locale (e. g. de-DE, en-GB, en-US).

Furthermore I created a decorator for the currencyFilter to make this filter stateful. However this will not work, because it is, as mentioned above, required to "Move the " var formats = $locale.NUMBER_FORMATS;" inside the returned function:" of the currencyFilter.

Would be great, when you let me know, what I have overlooked. How can I fix this issue without taken over the affected code from the angular project into my application and modify it there?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
6 participants