3
votes

I've gone through quite a few other questions on SO related to this Angular feature and none of the solutions seem to help my scenario. I'm utilizing the Angular Material tree component, and am attempting to generate a component within a fully expanded node.

My Tree.component.html:

<ng-container class="tree-content">
    <mat-card>
        <mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
            <mat-tree-node *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding>
                <ng-container *ngIf="node.expandable">
                    <button mat-icon-button matTreeNodeToggle [attr.aria-label]="'Toggle ' + node.name" (click)="generateTreeContent(node, treeControl.isExpanded(node))">
                        <mat-icon class="dark">
                        {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
                        </mat-icon>
                    </button>
                    <p>{{node.name}}</p>
                </ng-container>
                <app-dynamic></app-dynamic>
            </mat-tree-node>
        </mat-tree>
    </mat-card>
</ng-container>

My ViewChildren decorator declaration in Tree.component.ts:

@ViewChildren(DynamicComponent) children: QueryList<DynamicComponent>;

My Dynamic.component.ts:

@Component({
    selector: 'app-dynamic',
    templateUrl: './Dynamic.component.html',
    styleUrls: ['./Dynamic.component.scss']
})
export class DynamicComponent implements OnInit, AfterViewChecked {
    constructor(public componentFactoryResolver: ComponentFactoryResolver, public viewContainerRef: ViewContainerRef, public changeDetectorRef: ChangeDetectorRef, public ref: ElementRef) {
    }
    ...
}

Every time I try to access children, the QueryList yields no results.

Other things I've tried:

  • Using the 'read' metadata property:

    *.ts:

    @ViewChildren('dynamic', { read: DynamicComponent }) children: QueryList<DynamicComponent>;
    

    *.html:

    <app-dynamic #dynamic></app-dynamic>
    
  • Subscribing to the QueryList changes via AfterViewInit():

    public ngAfterViewInit(): void { 
        this.children.changes.subscribe((c: QueryList<DynamicComponent>) =>
        {
          ...
        });
    }
    
  • Using ContentChildren (Both with and without the 'read' parameter):

    *.ts:

    @ContentChildren('dynamic', { read: DynamicComponent }) children: QueryList<DynamicComponent>;
    

    *.html:

    <app-dynamic #dynamic></app-dynamic>
    
  • Accessing the component via Directive:

    @ViewChildren('dynamic', { read: DynamicDirective }) children: QueryList<DynamicDirective>;
    
  • Accessing after forcing change detection:

    this.viewContainerRef.detectChanges();
    console.log(this.children.toArray());
    

What am I doing wrong here?

In your Tree.component.ts when are you trying to access the children? You cannot access them in ngOnInit() it will be undefined at that point.Get Off My Lawn
I'm attempting to access the children in the generateTreeContent function called in the (click) defined in the html. And I've also tried in the change subscription of the children property, which should update with every change.Josh Ray
I assume that <app-dynamic> is in the inspector is that correct?Get Off My Lawn
Yes, I can see the tag in the inspector.Josh Ray
When you subscribe to changes, do you ever get the subscription to execute? Even if you expand the tree?Donald Duck