Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pipes: change detection on language change #11

Closed
wants to merge 3 commits into from

Conversation

SteveVanOpstal
Copy link

this.i18NextService.changeLanguage('new'); will now trigger Angular change detection in every pipe, this will update the page to 'new' language without having to refresh the page.

@coveralls
Copy link

coveralls commented Jan 31, 2018

Coverage Status

Coverage increased (+1.4%) to 91.193% when pulling 8c7e03a on SteveVanOpstal:master into 778fadf on Romanchuk:master.

@SteveVanOpstal
Copy link
Author

After some testing I noticed that by making the pipe impure (pure: false) change detection is triggered without having to subscribe to the languageChanged event and triggering a markForCheck(). So that is useless code, however maybe there's another solution.

When a pipe is pure Angular only creates one instance of the pipe and uses that for every pipe reference, when a pipe is impure Angular creates one instance per pipe reference, so the concept of subscribing to languageChanged needs multiple instances of the pipe. Otherwise only one of the pipes will be updated.
However the second difference between pure and impure is that transform will be called on every digest cycle, we don't want this. We already know when to trigger change detection.

I'm looking into creating a pure pipe that has multiple instances. For now I'll close this merge request.

@Romanchuk
Copy link
Owner

@SteveVanOpstal Hi, thank you for PR. Somehow i missed it.
In early versions i tryied to implement impure pipes, but left this idea for several reasons:

  1. Some custom controls or pipes can be dependent on angular LOCALE_ID token. So we want to change angular LOCALE_ID with i18next language.
{
 provide: LOCALE_ID,
 deps: [I18NextService],
 useFactory: (i18next: I18NextService) => {
  return i18next.language; //string: 'en', 'ru'...
 }
}

The problem is that angular IOC container resolves dependencies as singleton, once LOCALE_ID was requested it will always resolve as the same value (first resolved). The only way to get actual LOCALE_ID value is to register LOCALE_ID as factory function, but than it will break libraries that expect LOCALE_ID to be 'string' (not function).
Here is my stackoverflow question: Dynamicly get LOCALE_ID (resolve per request)

  1. Custom components with own localization support mostly require complete reinit on language change.

  2. Also most l10n, i18n and date format (momentjs) angular pipes are pure, and changing i18next language or LOCALE_ID won't trigger pipe change detection for them.

  3. Possible memory leaks and perfomant issues. For example zonejs automatically trigger change detection as a result of async operations, this means using jquery libs with ajax could cause your page (full of impure pipes) freeze.

That is why i ended up with simply refreshing page with a new language. We only need to setup right language, locale and formats on angular initialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants