Search code examples
angularservicesubject

Angular 9 Service to get configuration after login and after page reload


I'm not very experienced in Angular, but still learning. What I'm trying to do is to write a service in Angular 9 to get configuration object from app config (I have an endpoint from backend) after successful login and in case of page reload. My service:

import { Injectable } from '@angular/core';
import { OidcConfigurationClient, AppConfigurationDto } from './api-odm-manager.service';
import { Subject, Observable} from 'rxjs';


@Injectable({
  providedIn: 'root'
})
export class GetConfigurationService {

  private appConfig = AppConfigurationDto.fromJS({
    maxDaysForOrdersHistory: null
  });
  private subject = new Subject<AppConfigurationDto>();

  constructor(
    private readonly configService: OidcConfigurationClient
  ) { }

  public loadConfig() {
    this.configService.getDefaultOrderHistoryPeriod()
      .subscribe(config => {
        this.appConfig = config;
        this.subject.next(config);
      });
  }

  public getConfig(): Observable<AppConfigurationDto> {
    if (this.appConfig.maxDaysForOrdersHistory === null) {
      this.loadConfig();
    }
    return this.subject.asObservable();
  }
}

After successful login I call loadConfig() method and it doesn't work as it should. I mean it gets configuration from an endpoint, but getConfig() method returns this.subject.asObservable() in this case and it looks like it doesn't behave what I expect it to. When I reload the page and go to the component where I need this configuration object, it works fine, as this.appConfig.maxDaysForOrdersHistory is null, so the loadConfig is called.

In the component where I need configuration object:

  this.configurationService.getConfig().pipe(
      tap(days => {
          this.days = days.maxDaysForOrdersHistory;
          this.previousDate.setDate(this.date.getDate() - this.days);
          // some code that I need later
        })
      }))
      .subscribe(_ => {
          // this date is assigned earlier
          this.getOrdersHistory(this.previousDate, this.date);
      });

I'm confused as I'm quite new to Subject, could you please show me how to do this properly?


Solution

  • I see few issues:

    1. You are returning subject instead of data.
    2. you don't need to return anything if you are using subject. Raise an event, subject.next(yourdata) to update the data in service itself.
    3. You need to make subject as public and let your component subscribe to it when the event is raised.

    This is how I have used it in my app, hope it helps!

    @Injectable()
    export class DashboardService {
    
    objDashboardData: DashboardData;
    DashboardStatusChange: Subject<DashboardData> = new Subject<DashboardData>();
    
    updateSummary() {
        this.getSummary(this.dateRange)
            .subscribe(data => {
                this.objDashboardData = data;
                this.DashboardStatusChange.next(this.objDashboardData);
            });
        }
    }
    
    
    // In your component you need to subscribe to subject event change to get the data you need
    export class SidebarComponent implements OnInit {
    objDashboardData: DashboardData;
    
    ngOnInit() {
        this.dashboardService.DashboardStatusChange.subscribe(data => {
            this.objDashboardData = data;
        });
    }