Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async data not available in material bottom sheet component when also injecting data

When I pass custom data via the optional config object in material bottom sheet [open][1] method, my component data - if loaded asynchronously, is not available / doesn't render. If I hardcode the component data or don't pass a config object to the open function, the component data loads.

teams.component.ts - contains bottom sheet open method

export class TeamsComponent implements OnInit {
  teams: Team[];
  constructor(
    private teamService: TeamService,
    private messageService: MessageService,
    private bottomSheet: MatBottomSheet
  ) { }

    showActiveDivisionsInBottomSheet() {
        const ref = this.bottomSheet.open(ActiveDivisionsComponent, {
          data: { heading: 'Switch to new division' },
        });
    }
}

teams.component.html

<ul>
  <li *ngFor="let team of teams">
    {{ team.name }}
    <button (click)="showActiveDivisionsInBottomSheet()" mat-raised-button>{{ team.division.name }}</button>
  </li>
</ul>

active-divisions.component.ts - the component passed to the material bottom sheet

export class ActiveDivisionsComponent implements OnInit {
  divisions: Division[];
  constructor(
    @Inject(MAT_BOTTOM_SHEET_DATA) public data: any,
    private divisionsService: DivisionsService
  ) { }
  ngOnInit() {
    this.getDivisions();
  }
  getDivisions(): void {
    this.divisionsService.getDivisions()
      .subscribe(response => this.divisions = response['data']);
  }
}

active-divisions.component.html

<h1>{{ data.heading }}</h1>
<ul>
  <li *ngFor="let division of divisions">
    {{ division.name }}
  </li>
</ul>

Here, only the heading passed in through the config parameter of the bottom sheet open() method is rendered. Remove this config option and the divisions are loaded.

However - hardcode the divisions array in active-divisions.component rather than fetch it from the service:

divisions: Division[] = [
    {id: 1, name: 'Pool A'},
    {id: 2, name: 'Pool B'}
  ];

And both the data passed to the bottom sheet component, and the divisions array now render.

For this example I could obviously put the heading within the active-divisions component, but in reality I'll be passing the current division of the selected team, so that it can pre populate the bottom sheet.

like image 920
DJC Avatar asked Mar 06 '23 03:03

DJC


1 Answers

You need to trigger change-detection to update the sheet:

import { Component, OnInit, Inject, ChangeDetectorRef } from '@angular/core';

constructor(private changeDetectorRef: ChangeDetectorRef) { }

ngOnInit() {
    this.yourService.getData().subscribe(data => {
        // do your stuff and notify of changes like this
        this.changeDetectorRef.detectChanges();
    });
}
like image 92
yglodt Avatar answered Mar 07 '23 16:03

yglodt