Property 'Controls' Does Not Exist on Type 'Abstractcontrol' Angular 4 [Duplicate]
I Am Trying a Nested Reactive Form in Angular 4. It Is Working Fine but When I Try to Build Aot It's Throwing the Error 'Controls' Does Not Exist on Type...
I am trying a nested reactive form in Angular 4. It is working fine but when I try to build AOT it's throwing the error
'controls' does not exist on type 'AbstractControl'
I googled and tried few things but no luck. Could anyone tell me how to fix this issue?
<div [formGroup]="myForm">
<div formArrayName="addresses">
<div *ngFor="let address of myForm.get('addresses').controls; let i=index"
class="panel panel-default">
<span *ngIf="myForm.get('addresses').length > 1"
(click)="removeAddress(i)">Remove</span>
<div [formGroupName]="i">
<mat-form-field>
<input matInput formControlName="city" placeholder="city" value="">
</mat-form-field>
</div>
</div>
</div>
<a (click)="addAddress()" style="cursor: default"> Add +</a>
</div>
typescript code below
constructor(private _fb: FormBuilder) {
}
ngOnInit() {
this.myForm = this._fb.group({
addresses: this._fb.array([
this.initAddress(),
])
});
}
initAddress() {
return this._fb.group({
city: ['']
});
}
addAddress() {
const control = <FormArray>this.myForm.get('addresses');
control.push(this.initAddress());
}
removeAddress(i: number) {
const control = <FormArray>this.myForm.get('addresses');
control.removeAt(i);
}
Based on @Günter Zöchbauer comments , first i changed
myForm.controls['addresses'] to myForm.get('addresses') in both html and typescript
and then based on @yuruzi comment
changed myForm.get('addresses').controls to myForm.get('addresses')['controls']
Its working fine now. Thanks @gunter & yuruzi
You can fix it easily though. Outsource the "get the controls" logic into a method of your component code (the .ts file):
getControls() {
return (this.recipeForm.get('controlName') as FormArray).controls;
}
In the template, you can then use:
*ngFor="let ingredientCtrl of getControls(); let i = index"
This adjustment is required due to the way TS works and Angular parses your templates (it doesn't understand TS there).
Change myForm.get('addresses').controls to myForm.get('addresses').value will also fix the issue.
As an update to @sunny kashyap solution, I would write it this way:
getControls() {
return (this.recipeForm.get('controlName') as FormArray).controls;
}
for validation errors use...
<span *ngIf="f.YOUR_FORM_KEY.controls.YOUR_FORM_KEY.errors?.YOUR_FORM_VALIDATION">YOUR_FORM_KEY is YOUR_FORM_VALIDATION</span>
eg.
<span *ngIf="f.name.controls.name.errors?.required">Name is required</span>
ts file
get f(): any {
return this.userForm.controls;
}
to get the length of a FormArray , use simply length :
<span *ngIf="myForm.controls['addresses'].length > 1" (click)="removeAddress(i)">Remove</span>
Hope it helps
Can use a custom interface
// Define AbstractFormGroup
export interface AbstractFormGroup extends FormGroup {
controls: {
[key: string]: AbstractFormGroup & AbstractFormGroup[] & AbstractControl & FormGroup & FormArray,
}
}
// Usage example
class ... {
myForm: AbstractFormGroup
...
this.myForm = this.fb.group({...}) as AbstractFormGroup
}