2

I have to render a chain of components(say grids in blades) wherein after first component's data is loaded I will click on the data row of that component and it will open the next component. On click of data row of the next component, it will open another component and so on.

Approach that I am following - I have a shared service between all these components and whenever data is loaded for any component, that component calls next method on the BehaviourSubject of my service - this.service.dataLoadedEvent$.next(componentName)

My service method looks like -

public renderAllComponents(selectedOption, componentsToRender, componentsInfo): void {
    let componentInstance;

    for (let i = 0; i < componentsToRender.length; i++) {
      componentInstance = new componentsToRender[i](this);

      if (i === 0) {
        // For the component in the first/initial blade
        this.addFirstComponent(componentInstance[i]);
      }
      this.dataLoadedEvent$.subscribe((val) => {
         if (val === componentsInfo[i].name) {
           componentInstance.onSelect(selectedOption[componentsToRender[i].name]);
         }
      });
    }
  }

Components look like -

 public ngOnInit() {
    this.view = this.comp.pipe(
      tap(state => {
        this.isLoading = true;
      }),
      switchMap(state => {
        return this.orderService.fetch(state);
      }),
      tap(() => {
        this.isLoading = false;
        this.service.dataLoadedEvent$.next(this.constructor.name);
      })
    );
  }

But the problem here is, the for loop advances before service is notified about the data loading complete. So it sets the loop variable to the last value and the method is called on the last componentInstance which is not the expected behavior. Any help will be appreciated. Thanks in advance !

Ora
  • 1,889
  • 2
  • 9
  • 9

1 Answers1

0

PROBLEM:

The iterations in the loop get executed asynchronously, and hence, the waiting for the value does not happen.


Fix

This problem can be solved in 3 steps, as follows:

  1. Create a hidden element with the ID 'bladeTracker' (Example: <i id="bladeTracker">1</i>) and set its value to the initial blade number.

  2. Create an async function with an await on data loading, that updates the value of bladeTracker only when data is loaded.

  3. Write a function named 'showNextBlade()' that gets triggered whenever the value of bladeTracker element changes.

Gopinath
  • 4,066
  • 1
  • 14
  • 16