30

I have one component in Angular2 which is changing a "lang" class variable in my service translate.service.ts. In another component I am fetching a dict with the translation on init. If the first component changes the services language later, I want to refetch the dict in the second component automatically. How do I do that?

First component:

  setLang(lang) {
    this._translateService.setLang(lang);
  }

Service:

dict = { "en": {}};
lang = "en";

setLang(lang) {
    this.lang = lang;
}

getLang() {
    return this.dict;
}

Second component:

ngOnInit() {
    this.dict = this._translateService.getDict();
}
rablentain
  • 4,778
  • 10
  • 38
  • 80
  • In the service, do you modify `dict` or do you replace it? If you only modify it, the second component will automatically get/see the changes because it has a reference to the `dict` object (not a copy). – Mark Rajcok Mar 08 '16 at 17:54

1 Answers1

46

Edit:

Following the Mark's comment, a Subject / Observable should be preferred:

EventEmitter should only be used for emitting custom Events in components, and that we should use Rx for other observable/event scenarios.

Original Answer:

You should use an EventEmitter in the service:

export class LangService {
  langUpdated:EventEmitter = new EventEmitter();

  setLang(lang) {
    this.lang = lang;
    this.langUpdated.emit(this.lang);
  }

  getLang() {
    return this.dict;
  }
}

Components could subscribe on this event to be notified when the lang property is updated.

export class MyComponent {
  constructor(private _translateService:LangService) {
  }

  ngOnInit() {
    this._translateService.langUpdated.subscribe(
      (lang) => {
        this.dict = this._translateService.getDict();
      }
    );
  }
}

See this question for more details:

hugo der hungrige
  • 11,164
  • 8
  • 52
  • 80
Thierry Templier
  • 182,931
  • 35
  • 372
  • 339
  • 1
    With that said, you can use Subject.next() which is pretty much what [EventEmitter.emit](https://github.com/angular/angular/blob/master/modules/%40angular/facade/src/async.ts#L78) does. – Leo Caseiro Feb 09 '17 at 05:18
  • 1
    From what I understand EventEmitters should ONLY be used with @output? – Mackelito Sep 18 '17 at 08:42
  • 3
    Can you update the answer to reflect how to use Subject/Observable? – harishr Nov 08 '17 at 10:08
  • 2
    This answer definetly is correct. BUT is marked as bad practice ( YOU SHOULDN'T USE EVENT EMMITER on a service ). https://stackoverflow.com/questions/33380696/unable-to-figure-out-correct-eventemitter-or-observable-syntax-in-angular2-servi/33382275#comment54684990_33382275 – titusfx Feb 23 '18 at 10:27
  • 1
    so what's the best way then? I want to subscribe to my provider var but I want to do it inside the provider otherwise I need to change a lot of components – Dani Apr 30 '18 at 09:43