I'm trying to figure out how to dynamically render a form, and then cycle through each of the elements using @ViewChildren. However, the query appears not to be finding anything as I'm getting a zero length array back in ngAfterViewInit
at the bottom of the following code. (For reference, here's the Stackblitz: https://angular-4lqtap.stackblitz.io). I've found several articles relating to this topic, but none have solved the issue I'm facing.
import { Directive, Component, Input, OnInit, AfterViewInit, AfterContentInit, ViewChild, ViewChildren, ContentChildren, QueryList } from '@angular/core';
import {FormGroup, FormControl} from '@angular/forms';
@Directive({selector: '[foo]'})
export class IdVar {
// TODO(issue/24571): remove '!'.
@Input() idString !: string;
}
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1>
<form #myForm="ngForm" [formGroup]="form">
<ng-container *ngFor="let itm of testArr; let i = index">
{{i}}: <input [foo] [id]="i" />
<foo [idString]="i">{{i}}: </foo>
</ng-container>
</form>`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent implements OnInit, AfterViewInit {
@Input() name: string;
form: FormGroup;
formControls={};
testArr = ["a", "b", "c"];
@ViewChildren('foo') id: QueryList<IdVar>;
ngOnInit() {
this.form = new FormGroup(this.formControls);
this.testArr.forEach((itm)=>{
this.formControls[itm] = new FormControl(itm);
this.form.addControl(itm, this.formControls[itm]);
})
}
ngAfterViewInit() {
setTimeout(()=>console.log(this.id.length),1000);
}
}
Any idea what I'm doing wrong? Any solutions or workarounds? Tks!
NEW ADDITION BELOW (got rid of earlier "undefined" error):
app.module.ts
import { NgModule, NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
@NgModule({
imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }
There is some changes that you need to do:
You need to add the directive in the
declarations
in theapp.module.ts
.You are using a directive as a component, I think you dont need this line:
The ViewChildren works with classes not with the selector,so you should change the line:
to:
Another note, you don't really need the extra [] in the directive
I forked your example on stackblitz and modified it a little to make it work. I also changed the name of the directive to make it clear that it is a directive.
Live example here:
https://stackblitz.com/edit/angular-directive-viewchildren?file=src%2Fapp%2Fhello.component.ts