How to catch an asynchronous value when it's no longer undefined in a ionViewDidLoad?


#1

Hello,

I’m using the ngx-translate plugin, and when I start my application, I display a ion-select that allows the user to choose the language of my app.

The plugin detects the user language, so I would like my ion-select to display this language as a selectedItem / default value.

The problem is : the plugin takes a little time to get the user language, so when I use translate.currentLang in my ionViewDidLoad(), I get an undefined value, and my ion-select don’t have any selectedItem.

I tried using a setTimeout(() => { this.lang = this.translate.currentLang}, 1000), it works but maybe there is a better solution…

Do you have an idea on how to call translate.currentLang as soon as it is no longer an undefined value ?

Thanks


#2

post your code please


#3

here is my code:

.ts

import { Component } from '@angular/core'
import { IonicPage, NavController, NavParams } from 'ionic-angular'
import { TranslateService } from '@ngx-translate/core'

import { LoginPage } from '../login/login'
import { SignupPage } from '../signup/signup'

@IonicPage()
@Component({
  selector: 'page-bienvenue',
  templateUrl: 'bienvenue.html',
})
export class BienvenuePage {

  langApp: any
  
  constructor(
    public navCtrl: NavController, 
    public translate: TranslateService,
    public navParams: NavParams) {
  }

  ionViewDidLoad() {
    setTimeout(() => {this.langApp = this.translate.currentLang}, 1000)
  }

  onLangChange($event) {
    console.log($event)
    this.translate.use($event)
  }

  login() {
    this.navCtrl.push(LoginPage);
  }

  signup() {
    this.navCtrl.push(SignupPage);
  }
}

.hmtl

<ion-content padding>
  
  <ion-item no-padding no-lines no-margin>
    <ion-label margin-top center color="primary">{{"USER_PROFIL.LANGUE_DE_L_APPLICATION" | translate}}</ion-label>
    <ion-select interface="popover" [(ngModel)]="langApp" (ionChange)="onLangChange($event)">
      <ion-option value="fr">🇫🇷 Français</ion-option>
      <ion-option value="en">🇬🇧 English</ion-option>
    </ion-select>
  </ion-item>

</ion-content>

#4

Okay, waht about translate.current lang? How is that populated? I don’t see any of that code.


#5

I’m using this plugin

I have this in my app.component.ts :

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage:any = BienvenuePage;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, private translate: TranslateService,) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();
      translate.addLangs(["en", "fr"]);
      translate.setDefaultLang('en');

      let browserLang = translate.getBrowserLang();
      translate.use(browserLang.match(/en|fr/) ? browserLang : 'en');
    });
  }
}

And this in my app.module.ts :

export function HttpLoaderFactory(httpClient: HttpClient) {
  return new TranslateHttpLoader(httpClient, "./assets/i18n/", ".json");
}

...

 TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })

#6

I also have both en & fr .json files


#7

Gotcha, okay. Thanks, sorry never used the plugin before. So as you say your timeout works, and it’s a simple solution, but there are two possible downsides. The most likely is that you make your user wait a full second when the language loading only takes like 100ms or something. The less likely one is that it takes longer than one second to load the language and then your item is still undefined.

There are a couple ways to do this, but I would suspect you could simply just move all your translate related code outside the platform.ready block. Platform ready is only for native code related plugins, which this is not. So there’s no reason for you to wait for platorm ready, just do it in the constructor and it should work.

If for some reason that doesn’t work (it should), the translate service has an onLangChanged method you can subscribe to:

ionViewDidLoad() {
  this.translateService.onLangChange.subscribe((event: LangChangeEvent) => {
    this.langApp = event.lang; // or you could keep the assignment from currentLang
  });
}

#8

I’ve done the modifications and indeed it works :slight_smile:

I didn’t know that platform.ready was for native code related plugins.

Thank you for your help, well explained as always !