0

I have a button in my header that enables changing my app's language. I want the selected language to be available to all components via a service. I know how to send data from a service to a component ("consume a service") but I can't figure out how to send the data from the button to the service.

Here's the button:

  <mat-menu #menu="matMenu">
    <button (click)="change_L1_Language('en-US')">English<img width="50" alt="Flag of the United States" src="../assets/images/flags/us-flag.svg"></button>
    <button (click)="change_L1_Language('es')">Español<img width="50" alt="Flag of Spain" src="../assets/images/flags/es-flag.svg"></button>
    <button (click)="change_L1_Language('zh')">中文<img width="50" alt="Flag of China" src="../assets/images/flags/ch-flag.svg"></button>
    <button (click)="change_L1_Language('jp')">日本人<img width="50" alt="Flag of Japan" src="../assets/images/flags/jp-flag.svg" class="flag-border"></button>
  </mat-menu>

The controller handles the click:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { LanguageService } from '../language.service';

export class HeaderComponent implements OnInit {
  language: string = 'en-US';
  newLanguage: string = 'en-US';
  @Output() changeLanguageData: EventEmitter<string> = new EventEmitter<string>();

changeLanguage(newLanguage) {
    console.log(this.language);
    switch (true) {
      case (newLanguage === 'en-US'):
      this.language = 'en-US';
      break;

      case (newLanguage === 'es'):
      this.language = 'es';
      break;

      case (newLanguage === 'zh'):
      this.language = 'zh';
      break;

      case (newLanguage === 'jp'):
      this.language = 'jp';
      break;

      default:
      console.log("Error in switch-case.");
    }
    console.log(this.language);
    this.changeLanguageData.emit(this.language); // send data to parent
    this.LanguageService.changeLanguage().subscribe(); // receives data from a service, doesn't send data
  }

The controller is hooked up to LanguageService (a service) but the controller can only consume data from the service, it can't feed data to the service.

The controller also has an Event Emitter to send data to a parent component. This can't send data to a service because the service doesn't have an .html template for the link between components.

Looking at the Angular documentation, it shows how components within a family can communicate via a service: Parent and children communicate via a service. If I change this to

@Injectable({
  providedIn: 'root'
})

will this service provide the data to all components in my app?

The documentation also shows three methods for sending data from a parent component to the child component, which won't work because my service isn't a child of my component.

The documentation shows three methods for sending data from a child to a parent. The method I'm familiar with Parent listens for child event with an EventEmitter won't work because the service doesn't have an .html template to link the components.

1 Answer 1

4

You need to inject the service as a dependency like:

TS:

constructor(private languageService: LanguageHandler) { }

Then you can use it in your component to change stuff on click:

HTML:

<button (click)="changeLanguage("en-US")>Change to English</button>

TS:

changeLanguage(languageToChangeTo) {
  languageService.currentLanguage = languageToChangeTo;
}
Sign up to request clarification or add additional context in comments.

2 Comments

That works if I change the last line to this.languageService.changeLanguage(language);
It depends on how your service is written. If it's writtin in method change style your line is correct, but if you use getter and setter, my line would be correct, I think it's quite personal preference on what you use.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.