1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Anuncie Aqui
    Anuncie aqui você Também: fdantas@4each.com.br

Mat-tree not showing dynamically loaded children[]

Discussão em 'Angular' iniciado por Riziero, Julho 4, 2025.

  1. Riziero

    Riziero Guest

    Been messing with this for way too long. I am gonna show some code that's overly complicated because I wanted to exclude some potential culprits.

    My Angular component:

    import { Component, OnInit } from '@angular/core';
    import { EsrsDocumentService } from '../esrs-document.service';
    import { Router, ActivatedRoute } from '@angular/router';
    import { EsrsNode, EsrsTreeNode, SectionNode } from '../esrs-tree-node.model';

    import {NestedTreeControl} from '@angular/cdk/tree';
    import {MatTreeNestedDataSource} from '@angular/material/tree';


    @Component({
    selector: 'app-esrs-document-detail',
    templateUrl: './esrs-document-detail.component.html',
    styleUrls: ['./esrs-document-detail.component.css']
    })
    export class EsrsDocumentDetailComponent implements OnInit {

    treeControl = new NestedTreeControl<EsrsTreeNode>(node => node.children);
    dataSource = new MatTreeNestedDataSource<EsrsTreeNode>();

    constructor(
    private esrsDocumentService: EsrsDocumentService,
    private activatedRoute: ActivatedRoute
    ){}

    ngOnInit(): void {
    const docId = this.activatedRoute.snapshot.paramMap.get('id');
    // init datasource.data with esrs nodes
    this.esrsDocumentService.getEsrsNodes(docId).subscribe((nodes: EsrsNode[]) => {
    console.log("EsrsDocumentDetailComponent ngOnInit", nodes);
    this.dataSource.data = nodes.map(n => ({
    ...n,
    hasChild: n.hasChild,
    children: []
    }));
    });
    }

    loadChildren(node: EsrsNode) {
    if (node.children && node.children.length > 0) return;

    const docId = this.activatedRoute.snapshot.paramMap.get('id');
    this.esrsDocumentService.getSectionNodes(docId, node.id)
    .subscribe((sections: SectionNode[]) => {
    const treeNode = this.findNodeById(this.dataSource.data, node.id);
    if (treeNode) {
    // Cambia la referenza dei figli
    treeNode.children = sections.map(section => ({
    ...section,
    hasChild: false,
    children: []
    }));

    // Cambia la referenza del nodo padre nell'array radice
    const idx = this.dataSource.data.findIndex(n => n.id === treeNode.id);
    if (idx !== -1) {
    this.dataSource.data[idx] = { ...treeNode };
    }

    this.treeControl.dataNodes = this.dataSource.data;
    this.treeControl.expand(treeNode);
    this.dataSource.data = this.dataSource.data.slice();
    }
    });
    }

    // Trova il nodo nell'albero per id (ricorsivo)
    private findNodeById(nodes: EsrsTreeNode[], id: string): EsrsTreeNode | null {
    for (const node of nodes) {
    if (node.id === id) return node;
    if (node.children && node.children.length > 0) {
    const found = this.findNodeById(node.children, id);
    if (found) return found;
    }
    }
    return null;
    }
    trackById(index: number, node: any): string {
    return node.id;
    }

    hasChild = (_: number, node: EsrsTreeNode) => !!(node.children && node.children.length > 0 || node.hasChild);

    }


    then its HTML file, please note the initial <pre>{{ dataSource.data | json }}</pre>

    <pre>{{ dataSource.data | json }}</pre>
    <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree" [trackBy]="trackById">
    <!-- Nodo foglia -->
    <mat-tree-node *matTreeNodeDef="let node">
    {{ node.section || node.label || node.esrs }}
    </mat-tree-node>

    <!-- Nodo espandibile -->
    <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
    <div class="mat-tree-node">
    <button mat-icon-button matTreeNodeToggle
    [attr.aria-label]="'Toggle ' + (node.section || node.label || node.esrs)"
    (click)="loadChildren(node)">
    <mat-icon class="mat-icon-rtl-mirror">
    {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
    </mat-icon>
    </button>
    {{ node.section || node.label || node.esrs }}

    </div>
    <div role="group">
    <ng-container matTreeNodeOutlet></ng-container>
    </div>
    </mat-nested-tree-node>
    </mat-tree>


    Now the first screenshot before expanding the node and then what's shown after expanding: [​IMG]

    [​IMG]

    As you can the children[] is perfectly pupulated however but they are not being shown as part pf <mat-tree>. Here is the HTML taken from the page:

    <mat-tree
    _ngcontent-kya-c262=""
    role="tree"
    class="mat-tree cdk-tree example-tree"
    ng-reflect-data-source="[object Object]"
    ng-reflect-tree-control="[object Object]"
    ng-reflect-track-by="trackById(index, node) {
    "
    >
    <mat-nested-tree-node _ngcontent-kya-c262="" class="cdk-tree-node cdk-nested-tree-node mat-nested-tree-node ng-star-inserted" role="treeitem" aria-level="1" aria-expanded="true">
    <div _ngcontent-kya-c262="" class="mat-tree-node">
    <button _ngcontent-kya-c262="" mat-icon-button="" mattreenodetoggle="" class="mat-focus-indicator mat-icon-button mat-button-base" aria-label="Toggle ESRS E1 - Cambiamento climatico">
    <span class="mat-button-wrapper">
    <mat-icon _ngcontent-kya-c262="" role="img" class="mat-icon notranslate mat-icon-rtl-mirror material-icons mat-icon-no-color" aria-hidden="true" data-mat-icon-type="font"> expand_more </mat-icon>
    </span>
    <span matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round" ng-reflect-disabled="false" ng-reflect-centered="true" ng-reflect-trigger="[object HTMLButtonElement]"></span>
    <span class="mat-button-focus-overlay"></span>
    </button>
    ESRS E1 - Cambiamento climatico
    </div>
    <div _ngcontent-kya-c262="" role="group"><!--ng-container--></div>
    </mat-nested-tree-node>
    <!--ng-container-->
    </mat-tree>



    why the hell am I not seeing no <mat-tree-node> at all?!

    Continue reading...

Compartilhe esta Página