Search code examples
angulartypescriptrxjsbehaviorsubject

Unable to subscribe to BehaviourSubject


I have a weird issue. I have defined a BehaviourSubject in one service to propagate changes when user change language. In many components, when the BehaviourSubject change, I do stuff. It works in all components except one, and I don't know why.

My code:

@Injectable()
export class I18nLanguagesService {
  private activeLang: I18NLanguage = LANGUAGES.find(ln => ln.name === 'Español');
  activeLangSubject = new BehaviorSubject<I18NLanguage>(null);

  setActiveLang(language: I18NLanguage): void {
    this.activeLang = language;
    this.activeLangSubject.next(language);
  }

  getActiveLang(): I18NLanguage {
    return this.activeLang;
  }

  getLanguages(): I18NLanguage[] {
    return LANGUAGES;
  }

}

Declared in providers section in CoreModule, which is imported one time in app.module.

Usage:

Component 1 (defined in shared.module)

This one works, fine. Every time the subject emits a value, it does the call to the service.

 constructor(private statesServ: StatesService, private i18nSrv: I18nLanguagesService) {}
 this.i18nSrv.activeLangSubject
      .pipe(
        tap(() => {
          this.statesMultiCtrl.reset();
          console.log('SELECTOR | In tap')
        }),
        switchMapTo(this.statesServ.getStatesList())
      )
      .subscribe(states => {
        this.states = states;
        this.statesFiltered = this.states;
      });

Pipe (defined in shared.module)

It also works within a pipe :

export class AsyncI18nDatePipe implements PipeTransform {
  constructor(private i18nS: I18nLanguagesService) {}

  transform(value: Date | null | undefined, format = 'mediumDate', timezone?: string): Observable<string> {
    if (value) {
      return this.i18nS.activeLangSubject.pipe(map(localeId => formatDate(value, format, localeId.countryCode, timezone)));
    }
    return of('');
  }
}

The failure is in this component, defined also in shared.module:

  constructor(private formBuilder: FormBuilder, private valUsuServ: ValidationUsersService, private cmpServ: CampaignsService, private i18nService: I18nLanguagesService) {
    this.filters = this.formBuilder.group({
      idClient: new FormControl(null),
      idProject: new FormControl({ value: null, disabled: true }),
      sourceLanguage: new FormControl({ value: null, disabled: true }),
      targetLanguage: new FormControl({ value: null, disabled: true }),
      rangeDate: new FormGroup({
        dateFrom: new FormControl(null),
        dateTo: new FormControl(null),
      }),
      idItem: new FormControl({ value: null, disabled: false }),
      searchWords: new FormControl({ value: null, disabled: true }),
      itemState: new FormControl(null),
      category: new FormControl({ value: null, disabled: true }),
      validationUser: new FormControl({ value: null, disabled: true }),
      campaing: new FormControl(null),
      priorityOrd: new FormControl('asc'),
      dateOrd: new FormControl('asc'),
      categoryOrd: new FormControl('asc'),
      campaingOrd: new FormControl('asc'),
    });
  }

  ngOnInit(): void {
    this.i18nService.activeLangSubject.pipe(tap(lang => console.log('FILTERS | In tap -->', lang)));`
}

When I enter on the problematic componet, it logs all: Component on init

But when I change the language, only in the components that 'works', it log the changes :

change languages and log

I don't know why this behaviour happens, any help would be appreciated. Thanks for reading!!


Solution

  • In your "failed component". Try to subscribe to changes e.g.:

    this.i18nService.activeLangSubject.pipe(tap(lang => console.log('FILTERS | In tap -->', lang))).subscribe(() => console.log("changed"));