Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ViewChildren Querylist Array is empty when children are rendered with *ngFor

Tags:

angular

import { Component, OnInit, ViewChildren } from '@angular/core';
import { ChildComponent } from './child/child.component';

@Component({
    selector: 'app-parent'
    styleUrls: [],
    templateUrl: `<div>
                    <app-child *ngFor="let data of datas" [data]="data"></app-
                    child>
                  <div>'

export class ParentComponent implements OnInit {

@ViewChildren(ChildComponent) children;

Hello, as above I have several <app-child> components in Parent component rendered with ngFor. I'd like to access each child component's methods within the parent component. However, the Querylist keep returning an empty array.

Note that both parent and child components have been declared within the seperate root component's app-module. The child components renders no problem when parent's "datas" field is filled/changed. The problem is I just can't capture the rendered Child components in @ViewChildren decorator property.

Edit: Here's the console log:

QueryList {dirty: false, _results: Array(0), changes: EventEmitter}changes: 
EventEmitter {_isScalar: false, observers: Array(0), closed: false, 
isStopped: false, hasError: false, …}dirty: falsefirst: (...)last: 
(...)length: (...)_results: (4) [AnswerButtonComponent, 
AnswerButtonComponent, AnswerButtonComponent, 
AnswerButtonComponent]__proto__: Object

There seems to be two _results attribute in the query list, the first is empty second has 4 references to the child components.

How do I extract those?

like image 258
kshatriiya Avatar asked Nov 10 '17 07:11

kshatriiya


2 Answers

Nvm, I figured it out, the QueryList has changes property that you can subscribe to. My guess is when NgFor renders the components, the subscribe method returns the components.

this.children.changes.subscribe(c => { c.toArray().forEach(item => { 
console.log(item);}) });
like image 115
kshatriiya Avatar answered Oct 24 '22 00:10

kshatriiya


You have to subscribe to the changes of the ViewChildren as @kshatriiya mentioned.

Initialization of the viewChildren has to go inside ngAfterViewInit and wait for a next javascript event cycle to initialize.

Please find working prototype here - https://plnkr.co/edit/fBR3CtJ4wYfcPnIISVPW?p=preview

If you need more insight on the usage of ViewChild, ViewChildren, ContentChild, ContentChildren read this blog Thank you!

like image 6
Mohan Ram Avatar answered Oct 23 '22 22:10

Mohan Ram