1

I have a multi-language site which uses a dropdown select to allow the user to change language between English and German.

This is the footer component in my app and on the change of the selection the app runs the changeLanguage() function:

     constructor(
        private pageService: PageService,
        private router: Router,
        private el: ElementRef,
        private cd: ChangeDetectorRef,
        private meta: Meta,
        private route: ActivatedRoute
    ) { }

    ngOnInit(): void {
        var nativeElement: HTMLElement = this.el.nativeElement,
           parentElement: HTMLElement = <HTMLElement>nativeElement.parentElement;
        // move all children out of the element
        while (nativeElement.firstChild) {
           parentElement.insertBefore(nativeElement.firstChild, nativeElement);
        }
        // remove the empty element(the host)
        parentElement.removeChild(nativeElement);

        this.routerSub$ = this.router.events.subscribe(event => {
           if (event != null) {
               if (event instanceof NavigationEnd) {
                   this.languageCode = SiteContext.getLanguageCode(event.urlAfterRedirects);
                   if (this.languageCode == "en" && this.selectedLanguage.name == 'Deutsch') { this.selectedLanguage = this.languages[1]; }
               }
           }
        });
    }
    ngAfterViewInit() {
    }
    ngOnDestroy() {
        if (this.routerSub$ != null) this.routerSub$.unsubscribe();
        this.subscriptions.forEach((subscription: Subscription) => { subscription.unsubscribe(); });
        this.subscriptions = [];
    }
changeLanguage(lang) {
        let langCode: string = (lang.name == 'Deutsch' ? "de" : "en");
        this.router.navigate([langCode, 'home']);
    }

So this should redirect to either '/de/home' or '/en/home/' and the rest of the app picks up the language selection and loads content accordingly.

The first time the language options is changed this works perfectly, updating the URL and loading the new content. When the option is changed again nothing happens. The changeLanguage() function is run but nothing else.

It seems like this is constant with other SO issues around the detaching and reusing of routes in an Angular build (this is v5 btw). However nothing I've tried from other similar questions on SO fix the issue.

I've been focusing mainly on this question/answer without success - How to implement RouteReuseStrategy shouldDetach for specific routes in Angular 2. I'm also currently implementing the CustomReuseStrategy class from this answer.

For further information:

app.routing.ts:

const appRoutes: Routes = [
    //{ path: '', redirectTo: '/de/home', pathMatch: 'full' },
    { path: 'de/v2-home', component: HomeComponent, data: { animation: 'de/v2-home' } },
    { path: '', redirectTo: '/de/v2-home', pathMatch: 'full' },
    { path: ':lang/v2-home', component: HomeComponent, data: { animation: ':lang/v2-home' } },
];

app.module.ts:

import { RouteReuseStrategy } from "@angular/router";
@NgModule({
    [...],
    providers: [
        {provide: RouteReuseStrategy, useClass: CustomReuseStrategy}
    ]
)}
export class AppModule {
}

Just not sure if I'm missing something in my implementation with the navigating here?

Thanks.

t.c.
  • 53
  • 6
  • 1
    Could you create a [mcve] using plunker, stackblitz or some similar tool ? That would add value and help other people answer this (interesting) question. – Pac0 Apr 24 '18 at 15:51

1 Answers1

0

The code that actually changes the language must be decoupled from ngOninit(). What I mean is, that you shouldn't be reloading the entire component just for changing the language.

You should subscribe to your route parameters through the 'ActivatedRoute' feature.

import { ActivatedRoute } from '@angular/router';

Then inject it into your component:

constructor (private _route : ActivatedRoute){}

Then inside ngOnInit subscribe to your route parameter i.e 'lang':

ngOninit()
{
    this._route.params.
    subscribe(params => 
    {
       this.changeLanguage(params[":lang"]);
       //Any incoming parameter must be sanitized for obvious reasons.
    }
}

changeLanguage(language)
{
    //change language logic here
}

The user's choice should then be passed as a parameter the changeLanguage() function.

P.S - If it helps, here is my boilerplate for angular 2+ : https://github.com/oneinazillion/CEVI

Ashish Koshy
  • 131
  • 1
  • 7