3

I am trying to get control over the children instances of a component and can't go past an error. I am trying to follow along the answers from this issue.

The parent component Sequence contains children components of SequenceStep. The parent contains the following declaration:

@ViewChildren(SequenceStep) steps: QueryList<SequenceStep>;

then I am trying to do something about the children:

ngAfterViewInit() {
    this.steps.changes.subscribe(steps => {
        console.log(steps);
    });
}

The error I'm getting is:

metadata_resolver.js:639 Uncaught Error: Can't construct a query for the property "steps" of "Sequence" since the query selector wasn't defined.

whereas both Sequence and SequenceStep components do have their selectors defined in their @Component decorators (sequence and sequence-step respectively).

What am I doing wrong here?

Community
  • 1
  • 1
user776686
  • 7,933
  • 14
  • 71
  • 124
  • 1
    Can you reproduce in a plunker? – Günter Zöchbauer Oct 10 '16 at 12:37
  • @GünterZöchbauer Sorry, it took me a while to recreate the plnkr, but here it is: https://plnkr.co/edit/tusSBpbmyoG6TQTcV2i0?p=preview It is not working (please see the console) - the question is: is the code correct? – user776686 Oct 14 '16 at 21:32

4 Answers4

3

Have you tried adding quotes to your @ViewChildren arg?

@ViewChildren('SequenceStep') steps: QueryList<SequenceStep>;

lmetdaoui
  • 31
  • 1
2

This issue can be related to the import of SequenceStep, check the class name of the related import row.

Serg Maks
  • 21
  • 2
  • Agreed. Also if you have a Directive (the ViewChild) that is defined in the same file as the parent Component, then the Directive definition must come first. – Miller Jun 16 '17 at 13:28
1

There are a few things

  • If you pass children from the outside, they are content not children. @ViewChild() only works for children added to the template of a component directly.

    @ContentChildren() works on transcluded content:

    @ContentChildren(TheChild) kids: QueryList<TheChild>;
    
  • this.kids.changes() only notifies about changes after the initialization. Therefore just access this.kids directly in ngAfterViewInit() and then subsribe to get notified about later changes

    ngAfterViewInit() {
      this.myKidsCount = this.kids.length;
      this.cdRef.detectChanges();
    
      this.kids.changes.subscribe(kids => {
          this.myKidsCount = kids.length;
      });
    }
    
  • Angular doesn't like when change detection causes changes. ngAfterViewInit() is called by change detection, this is why this.myKidsCount = this.kids.length causes an exception.

To work around I invoke change detection explicitly after changing the property myKidsCount:

constructor(private cdRef:ChangeDetectorRef){}

ngAfterViewInit() {
  this.myKidsCount = this.kids.length;
  this.cdRef.detectChanges();
}

Plunker example

superjos
  • 12,189
  • 6
  • 89
  • 134
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
1

@ViewChildren('SequenceStep') steps: QueryList<SequenceStep>;

Worked for me. Angular 4.X.X Angular CLI 1.X.X

phacic
  • 1,402
  • 1
  • 14
  • 21