Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular material displayWith isn't working with ngx-translate

I am using [displayWith] directive in my mat-autocomplete. It works fine when i am manually selecting values but when i reload the page i am not getting translation. Parameter necessary for translation is asynchronously loaded from query params in ngOnInit. So I rely on async parameter but my displayFunction() is sync function. How to resolve that?

Without [displayWith] function everything is working OK but without translation (it's just displaying pure values what i do not want). So i am sure that rest of the code is proper.

My mat-autocomplete:

<mat-form-field [formGroup]="cityForm"
                appearance="outline"
                floatLabel="never"
                color="primary">
  <mat-icon matPrefix>location_on</mat-icon>
  <input type="text" placeholder="{{ 'job_offer_search_bar.job-offer-search-bar-city-form.placeholder' | translate }}"
         aria-label="Number" matInput
         formControlName="cityControl" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" (optionSelected)="onSelectionChanged($event.option.value)"
                    [displayWith]="displayFn.bind(this)">
    <mat-option>
      {{ 'job_offer_search_bar.job-offer-search-bar-city-form.all' | translate }}
    </mat-option>
    <mat-option *ngFor="let city of filtredCities | async" [value]="city">
      {{ 'job_offer_search_bar.job-offer-search-bar-city-form.city' | translate:"{ city: '" + city +"' }"}}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

My displayWith function is below:

displayFn(val: string){
    if (!val) return '';
    let stringToReturn;
    this.translate.get('job_offer_search_bar.job-offer-search-bar-city-form.city', {city: val}).subscribe(value => {
      console.log('inside subscribe', value);
      stringToReturn = value;
    });
    console.log('after sub', stringToReturn);
    if (stringToReturn != undefined) {
      return stringToReturn;
    } else {
      return 'Sorry, value has not been translated';
    }

Console.log in subscribe is invoked after console.log after subscribe. So subscribe is made after i get my parameter for translation, so after my return... I need some trick or tip to pass my translated string as a return.

I assume that there is a way to do that. Any help will be appreaciated.

like image 770
Shaiby Avatar asked Nov 07 '22 20:11

Shaiby


1 Answers

Observables are, at the most cases, async functions. Depending on your implementation you may use translate.instant

displayFn(val: string) {

  const defaultMessage = 'Sorry, value has not been translated';
  return val
    ? this.translate.instant('job_offer_search_bar.job-offer-search-bar-city-form.city', { city: val }) || defaultMessage
    : '';

}

If the instant function is called before the translation file is loaded, it will return undefined.

EDIT:

displayFn(val: string) {

  const translate$ = this.translate.get('job_offer_search_bar.job-offer-search-bar-city-form.city', { city: val }).pipe(
    map(translatedText => translatedText || 'Sorry, value has not been translated')
  )

  return val
    ? translate$
    : of('');

}


[displayWith]="displayFn.bind(this) | async"
like image 63
Leandro Lima Avatar answered Nov 10 '22 00:11

Leandro Lima