Search code examples
angularrecursiontreecomponentsangular8

mat-accordion is lagging when calling angular component in it recursively


I'm calling a component recursively in accordion to show tree like structure.

The code is working for short input but it is lagging on recursive calls for nested data

It is just like a json tree.

//sample.component.html
<app-tree [input]="data"></app-tree>


//tree.component.html

    <mat-accordion>
        <mat-expansion-panel hideToggle="true" (click)="toggleTree($event, input)">
          <mat-expansion-panel-header>
            <mat-panel-title>
                <mat-icon>{{input.buttonName}}</mat-icon>
                {{input.key}}
            </mat-panel-title>
          </mat-expansion-panel-header>
          <ul class="main-obj">   // tried *ngIf here
             <div class="obj-list" *ngFor="let item of input.value; trackBy: trackChanges">
                <li>
                  {{item.key}}: {{item.value}}
                </li>
                <li style="list-style: none; margin-left: -40px;">
                    <app-tree [input]="item"></app-tree>
                </li>
            </div>
         </ul>
        </mat-expansion-panel>
    </mat-accordion>

//tree.component.ts

    import { Component, OnInit, Input, Output } from '@angular/core';
    import { EventEmitter } from 'events';

    @Component({
      selector: 'app-tree',
      templateUrl: './tree.component.html',
      styleUrls: ['./tree.component.css']
    })

    export class TreeComponent implements OnInit {
        @Input() input: any;

        @Output() click = new EventEmitter();

        constructor(){}

        ngOnInit(){
        }

        toggleTree(event, toggleButton) {
            event.stopPropagation();
            if(toggleButton.buttonName == 'add')  
                toggleButton.buttonName = 'remove';
            else
                toggleButton.buttonName = 'add';
        };

        trackChanges = (index) => {
            return index;
        }
    }

I've tried placing ngIf (as shown in the code before ngFor) but is not that much effective.

Is there any way to load component when opening accordion?

Thanks!


Solution

  • Answering to your question:

    Is there any way to load component when opening accordion?

    Yes, there is, but I'm not sure it's gonna solve a lagging problem. Anyway, try to wrap the expansion panel's content in a ng-template containing the matExpansionPanelContent attribute. It'll lazy load its content (see the docs).

    <mat-accordion>
      <mat-expansion-panel hideToggle="true" (click)="toggleTree($event, input)">
        <mat-expansion-panel-header>
          <mat-panel-title>
            <mat-icon>{{input.buttonName}}</mat-icon>
            {{input.key}}
          </mat-panel-title>
        </mat-expansion-panel-header>
    
        <ng-template matExpansionPanelContent>
          <ul class="main-obj">   // tried *ngIf here
            <div class="obj-list" *ngFor="let item of input.value; trackBy: trackChanges">
              <li>{{item.key}}: {{item.value}}</li>
              <li style="list-style: none; margin-left: -40px;">
                <app-tree [input]="item"></app-tree>
              </li>
            </div>
          </ul>
        </ng-template>
      </mat-expansion-panel>
    </mat-accordion>