angulartypescriptdatasourceangular-material-tableangular-changedetection

How to update angular mat-table if the drawer is in another component?


Main component has tabs, component A, B etc.

My component_A has preloaded data but I have a button for filter. I have a button that toggles a drawer from another component (main component).

 toggleDrawer(): void {
    this.drawerService.toggleDrawer(); // Call service to toggle drawer
  }

main component:

        <mat-drawer-container class="drawer-container" autosize>
      <div class="main-component-container">
        <div class="mat-tab-grp">
          <nav
            class="nav-bar"
            mat-tab-nav-bar
            #tabGroup
            mat-stretch-tabs
            color="accent"
          >
            <a
              mat-tab-link
              *ngFor="let link of navLinks"
              [routerLink]="link.link"
              routerLinkActive
              #rla="routerLinkActive"
              [active]="rla.isActive"
            >
              <mat-icon>{{ link.icon }}</mat-icon>
              {{ link.label }}
            </a>
          </nav>
          <div class="ng-temp">
            <router-outlet></router-outlet>
          </div>
        </div>
      </div>
    <mat-drawer
        #drawer
        class="example-sidenav mat-elevation-z2"
        mode="side"
        position="end"
      >
<form [formGroup]="filterGroup" class="filter-fields">
some codes
</form>
    </mat-drawer>
    </mat-drawer-container>

ts file:

 this.drawerService.toggleDrawer$.subscribe(() => {
        this.drawer.toggle(); // Toggle the drawer
      });

and this has button that fetches data

submitForm() {
this.dataService
        .fetchData(someParameters)
        .subscribe(
          (response) => {
              this.drawer.close(); //this closes the drawer then should update the mat-table in the component A.
            }
}

in the dataService: ....this.dataSourceSubject.next(tmp_table);

After the drawer closes and the toggleDrawer() finishes, I want the mat-table to update too. It only updates when I go to other tabs, since this component A is in a mat-tab. That's the time it refreshes the table. I also can't make it reload the page because the preloaded data will be fetched again. So I just want the table to update.

enter image description here


Solution

  • I think the problem is that the BehaviourSubject should emit the latest data from the API call and not the previous data.

    fetchData(someParameters): Observable<any[]> { 
        return this.service.GetData(enc_param).pipe( 
          map((response: any) => { 
            this.dataSourceSubject.next(response); // <- changed here!
            return tmp_ta 
          })
        );
    }
    

    The problem could also be in how the mat-table and component A receive the data from your BehaviorSubject.


    Async Pipe

    In your service, make sure you have an observable of the BehaviorSubject.

    dataSourceSubject: BehaviorSubject<any> = new BehaviorSubject<any>([]);
    dataSourceObservable$!: Observable<any>;
    
    constructor() {
      this.dataSourceObservable$ = this.dataSourceSubject.asObservable();
    }
    

    Access this on the component using getter so that is can be used in HTML.

    get dataSource$ () {
        return this.dataService.dataSourceObservable$;
    }
    

    Finally when you make use of this property, use the async pipe.

    <table mat-table [dataSource]="dataSource$ | async" class="mat-elevation-z8">
    

    Direct Binding.

    Same approach as above, but subscribe and get the data and send to the mat-table.

    ngOnInit() {
        this.sub.add(
           this.dataService.dataSourceObservable$.subscribe((data: any) => {
             this.data = data;
           })
        );
    }
    
    ngOnDestroy() {
        this.sub.unsubscribe();
    }
    

    Finally when you make use of this property directly.

    <table mat-table [dataSource]="data" class="mat-elevation-z8">