Search code examples
javascriptangulartypescriptrxjsangular-changedetection

How to update the data in the view when observable data gets updated?


I am subscribing to an observable (getContentfulEntry) to get some data but also passing the data from another observable (stateService)

this.langSubscription = this.stateService.getLanguage()
      .subscribe(val => {
        this.lang = val;
      });
      
    this.subscription = this.contentfulService.getContentfulEntry(this.footerEntryId, {locale: this.lang.toLowerCase()})
      .subscribe(res => {
        console.log('Footer Entries:: ', res);
        // this.contentfulData = res;
        this.filteredFooter = this.contentfulService.getFilteredEntryByProv(res, this.prov);
        console.log('Filtered Footer:: ', this.filteredFooter);
      });

to it as a parameter. So new data is fetched when this.lang is updated. However, this.subscription doesn't update the data in the view unless I hit refresh on it. Any idea what am I doing wrong or how I can fix this?


Solution

  • You are referencing the value of the data returned from stateService.getLanguage() (possibly) before getLanguage() has returned a value.

    Ensure that this.lang has a value by making your call to getContentfulEntry() within your subscription to getLanguage(). This will ensure that this.lang has a value when calling getContentfulEntry()

    this.langSubscription = this.stateService.getLanguage()
      .subscribe(val => {
        this.lang = val;
        this.subscription = this.contentfulService.getContentfulEntry(this.footerEntryId, { locale: this.lang.toLowerCase() })
          .subscribe(res => {
            console.log('Footer Entries:: ', res);
            // this.contentfulData = res;
            this.filteredFooter = this.contentfulService.getFilteredEntryByProv(res, this.prov);
            console.log('Filtered Footer:: ', this.filteredFooter);
          });
      });
    

    You could also consider assigning the returned value from getLanguage() to a BehaviorSubject (from rxjs) which acts as an Observable. You are able to subscribe to your BehaviorSubject, which will emit a value every time a new value is assigned. I mention behavior subjects as a way to manage parameters that might change over time, but don't consider this solution best practice in this use case.

    lang = new BehaviorSubject<string>('');
    
    this.langSubscription = this.stateService.getLanguage()
      .subscribe(val => {
        // this.lang will emit the next assigned value "val"
        this.lang.next(val);
      });
    
    // subscribe to emitted value from this.lang
    this.lang.subscribe(val => {
      this.subscription = this.contentfulService.getContentfulEntry(this.footerEntryId, { locale: this.lang.getValue().toLowerCase() })
        .subscribe(res => {
          console.log('Footer Entries:: ', res);
          // this.contentfulData = res;
          this.filteredFooter = this.contentfulService.getFilteredEntryByProv(res, this.prov);
          console.log('Filtered Footer:: ', this.filteredFooter);
        });
    });