1

How can you know if a lazy loaded component has been rendered? I have the following HTML:

<mat-accordion>
  <mat-expansion-panel>
    <mat-expansion-panel-header>
      Panel Summary
    </mat-expansion-panel-header>
    <ng-template matExpansionPanelContent>
      <some-component></some-component>
    </ng-template>
  <mat-expansion-panel>

  .... more panels with the same component

<mat-accordion>

By default the panels are closed so <some-component> has not been rendered yet.

Then in the typescript I have the following code:

@Component({
  selector: 'main-component',
  templateUrl: './main-component.html',
  style: ''
})
export class mainComponent implements OnInit {

  @ViewChild(SomeComponent, {static: false})
  someComponent: SomeComponent;

  onButtonClick() {
     this.someComponent.update();
  }

Say the panels haven't been opened yet and the user clicks on the button I get the following error:

mainComponent.html: ERROR TypeError: Cannot read property 'update' of undefined

I know this is because the actual components are not loaded yet and we are trying to call its function. I want to keep lazy loading the panels to reduce the performance issues for having dynamic things in an angular materials expansion panel.

I can think of only one solution and its to not lazy load which isn't really an option. Any other solutions? Is there a way to know if ViewChild is undefined or is there a flag where viewChild will tell you if it found those components?

Clev_James23
  • 171
  • 1
  • 3
  • 15
  • https://stackoverflow.com/questions/43764536/angular-access-inner-component-of-ng-template check this one. – Vova Bilyachat Oct 17 '19 at 00:45
  • No luck with that as I am using Angular v8. I also looked into using ContentChild but that did not work as well. To be specific, I tried the following ```@ContentChild(SomeComponent, {static: false}) someComponent: SomeComponent``` and I also tried ```@ViewChild(SomeComponent, {descendants: true})``` but this threw errors since ```{static: false}``` needed to be declared – Clev_James23 Oct 17 '19 at 02:10

1 Answers1

0

If your component isn't actually loaded then how can you expect to call the update on it? What is SomeComponent?

One thing I can think of that you can do is something like this:

<mat-accordion>
  <mat-expansion-panel #someComponentExpansionPanel>
    <mat-expansion-panel-header>
      Panel Summary
    </mat-expansion-panel-header>
    <ng-template matExpansionPanelContent>
      <some-component [updateOnOpen]="updateOnOpen"></some-component>
    </ng-template>
  <mat-expansion-panel>

  .... more panels with the same component

<mat-accordion>

@Component({
  selector: 'main-component',
  templateUrl: './main-component.html',
  style: ''
})
export class mainComponent implements OnInit {

  @ViewChild(SomeComponent, {static: false})
  someComponent: SomeComponent;

  @ViewChild('someComponentExpansionPanel', {static: false})
  someComponentExpansionPanel: MatExpansionPanel;

  private _updateOnOpen = false;

  get updateOnOpen(): boolean {
    return this._updateOnOpen;
  }

  onButtonClick() {
     if ( this.someComponent ) {
       this.someComponent.update();
     } else {
       this._updateOnOpen = true;
       this.someComponentExpansionPanel.open();
     }
  }

You'll need to implement the updateOnOpen input in the SomeComponent.

AlmaniaM
  • 217
  • 2
  • 5