Search code examples
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>
  • I am using the dropdown in other scenarios, so I can't hardcode a default value

  • I'm sure that there is a solution to translate the value in the parent component ts and feed it to the html, but I don't understand why the pipe does not work, as I would rather do that

  • I have triple checked that my translation files are properly setup - all other translations for my app works fine


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;
      }
    }