angularngx-translate

ngx-translate returning empty string when translating component input property


I have used ngx translate for my entire project, and it works fine - except in this case.

I have to translate an input property from the parent component, to a child component 'dropdown'.
But the output is simply an empty string! It works with a hardcoded string, but not the translated one - simply nothing gets displayed, not even the translation key.

I have properly setup the translation in my language files, and it works in other scenarios, but not here.

Image of empty dropdown using translation.

Image of dropdown with hardcoded title input value.

This is the html form my parent component:

<dropdown
      [title]="'TimePeriod_Last30Days' | translate"
      [items]="[
                'Last 7 days',
                'Last 30 days',
                'Last 90 days',
                'Last 12 months'
                ]"
      (optionSelected)="onTimePeriodSelected($event)"
/>

This is my dropdown component:

import { Component, Input, ElementRef, Renderer2, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'dropdown',
  templateUrl: './dropdown.component.html',
  styleUrls: ['./dropdown.component.scss'],
})
export class DropdownComponent {
  @Input() items: string[] = [];
  @Input() title: string;// THIS STRING IS USED FOR DEFAULT DROPDOWN OPTION 
  @Output() optionSelected = new EventEmitter<string>();
  isOpen = false;
  selectedOption: string;
  
  constructor(private eRef: ElementRef, private renderer: Renderer2) {
    this.renderer.listen('window', 'click', (e: Event) => {
      if (!this.eRef.nativeElement.contains(e.target)) {
        this.isOpen = false;
      }
    });
  }
  
  ngOnInit() {
    this.selectedOption = this.title;
  }

  toggleDropdown() {
    this.isOpen = !this.isOpen;
  }

  selectOption(option: string) {
    this.selectedOption = option;
    this.isOpen = false;
    this.optionSelected.emit(this.selectedOption);
  }
}

The title string is used for the default dropdown option:

<div class="dropdown"> 
  <button class="dropdown-button" (click)="toggleDropdown()" [class.open]="isOpen">
    {{ selectedOption }} <i class="ci-Chevron_Down" id="chevron-down" [class.rotated]="isOpen"></i>
  </button>
  <div class="dropdown-content" *ngIf="isOpen">
    <p *ngFor="let item of items" (click)="selectOption(item)">{{ item }}</p>
  </div>
</div>

Solution

  • The problem is timing. Translating with the translate pipe is an asynchronous action. At the moment when you are trying to apply the title in ngOnInit(), the title input does not yet contain the translated value. To fix it, you can perform your logic in an input setter instead of ngOnInit():

    @Input() set title(title: string) {
      if (title) {
        this.selectedOption = title;
      }
    }