How to update a value provided by a provider in Angular?

Viewed 1625

I have a provider in AppModule which provides a class.

Is there a way to update the provided value at runtime?

{provide: MatDatepickerIntl, useClass: SomeClass}

How can replace SomeClass with AnotherClass at runtime (i.e.: when reacting to an event in a component).

I'm using Angular 9.

EDIT

I know could use useFactory to generate the provided value based on some logic. The problem with that approach is that the factory function still runs just once, when the component is created.

What I wanna do is run that function again whenever some event occurs. How can I do that?

EDIT2:

So app.module does this:

// this is in providers array...
     {
          provide: MatDatepickerIntl, deps: [DatePickerIntlService],
          useFactory: (datePickerIntl) => datePickerIntl.getLocale()
     }

The above service reads current locale and it returns a MatDatepickerIntl subclass instance accordingly, so it creates the correct class.

Finally I have the event in app component ngOnInit:

onLangChange.subscribe(() => {
          
        })

How do I change the provided MatDatepickerIntl subclass in the event handler? I can call the service but there is no way to update the provided value with the result...

Material Date Picker expects MatDatepickerIntl token to return the desired subclass. That is how it loads localized texts.

Hope this clarifies things a bit better.

Thanks in advance!

1 Answers

You have to make a parent Service, which will reroute to the expected service:

@Injectable({
  providedIn: 'root'
})
export class MyParentService {
  childService: ChildEnService | ChildFrService | ChildEsService;
  private ngDestroy$: Subject<void> = new Subject();

  constructor(private childEnService: ChildEnService,
              private childFrService: ChildFrService,
              private childEsService: ChildEsService,
              private languageObsService: LanguageObsService) {
    this.languageObsService.getCurrentLanguage().pipe(
                                                 takeUntil(this.ngDestroy$)
                                               ).subscribe(
                                                 newLanguage => this.updateChild(newLanguage);
                                               );
  }

  public getMyPreciousData() {
    return this.childService?.getMyPreciousData();
  }

  private updateChild(newLanguage: LanguageEnum) {
    swtich(newLanguage) {
      case LanguageEnum.en:
        this.childService = this.childEnService;
        break;
      case LanguageEnum.fr:
        this.childService = this.childFrService;
        break;
      case LanguageEnum.es:
        this.childService = this.childEsService;
        break;
    }
  }

  private ngOnDestroy() {
    // unsubscribe the languageObsService
    this.ngDestroy$.next();
    this.ngDestroy$.complete();
  }
}


@Injectable({
  providedIn: 'root'
})
export class LanguageObsService{
  currentLanguage$: BehaviorSubject<LanguageEnum> = new BehaviorSubject(LanguageEnum.en);

  constructor() {}

  public getCurrentLanguage(): Observable<LanguageEnum> {
    return this.currentLanguage$.asObservable();
  }

  public setCurrentLanguage(newLanguage: LanguageEnum): void {
    this.currentLanguage$.next(newLanguage);
  }
}
Related