I had a fully functioning code in Angular 8. I decided to upgrade from 8 to Angular 12.
I have a dynamic reactive form. The form is of question answer format. Based on who is login in the questions change. The answer is of Yes/No format. Based on who is login in and what answer option is chosen textbox dropdown and checkbox or all the there mentioned appreas.
Here is my code for the form
Component.ts
constructor(
private router: Router,
private datePipe: DatePipe,
private route: ActivatedRoute,
private formBuilder: FormBuilder) {
this.dynamicForm = this.formBuilder.group({
questions: new FormArray([])
});
this.CreateForm();
}
get f() { return this.dynamicForm.controls; }
get t() { return this.f.questions as FormArray; }
CreateForm() {
if (this.formdetail.questionList) {
// CREATE Questions
if (racialQues !== this.formdetail.questionList[i].quetext && this.formdetail.questionList[i].quetext !== auditQues) {
this.t.push(this.formBuilder.group({
quesIndex: [i 1],
...
controlName: [this.formdetail.questionList[i].selectedAns, [Validators.required]]
}));
} else if (this.formdetail.questionList[i].quetext === auditQues) {
this.t.push(this.formBuilder.group({
quesIndex: [i 1],
......
selectedValue: [this.formdetail.auditTrail.selectedValue, this.reasonValidator],
}));
} else if (this.formdetail.questionList[i].quetext === racialQues) {
this.t.push(this.formBuilder.group({
quesIndex: [i 1],
......
selectedAuxAns: [this.formdetail.questionList[i].val, [this.auxAnsValidator]]
}));
}
}
}
Here is the html
<form [formGroup]="dynamicForm">
<!-- Question Start -->
<div *ngFor="let ticket of t.controls; let i = index">
<div [formGroup]="ticket" class="form-row">
<div class="input-group col-md-12" style="padding: .15em .5em">
<div class="input-group-prepend col-md-10" style="padding: 0; margin: 0;">
<label class="input-group-text w-15">{{i 1}}</label>
<label class="input-group-text w-100" style="text-align: left; white-space: normal;">{{ticket.controls.name.value}}</label>
</div>
<select formControlName="controlName" class="form-control col-md-2" style="height:auto !important;"
[ngClass]="{ 'is-invalid': submitted && ticket.controls.controlName.errors }"
(change)="onChange($event.target.value, i)">
<option [ngValue]="null"> --Select-- </option>
<option *ngFor="let ansItem of formdetail.questionList[i].answerList" [ngValue]="ansItem" >{{ansItem.anstext}}</option>
</select>
<div *ngIf="submitted && ticket.controls.controlName.errors" class="invalid-feedback" style="height:auto !important;"
[ngClass]="{ 'input-group-append': submitted && ticket.controls.controlName.errors,
'col-md-1': submitted && ticket.controls.controlName.errors }">
<div *ngIf="ticket.controls.controlName.errors.required">Required</div>
</div>
.
.
.
.
</div>
/div>
</div>
<!-- Question End -->
</form>
Now I am getting error in "ticket.control" Property 'controls' does not exist on type 'AbstractControl'. I am not sure why i am getting this error after upgrade. I have tried ticket.['control']. or ticket.get('controlName') as suggested by other article of similar error in stackoverflow but nothing works
Here is the snapshot of error
Any help will be appreciated. Thanks
CodePudding user response:
'controls' isn't a property of an AbstractControl. instead you can use your form group, so 'dynamicForm.controls.controlName'
CodePudding user response:
your t
is of type FormArray
, FormArray.controls
array is of type AbstractControl[]
, thus, each ticket
at
<div *ngFor="let ticket of t.controls; let i = index">
line is of type AbstractControl
, which does not have controls
property as is seen in TS error in your screenshot. TS does not know that each ticket
actually is of type FormGroup
(set here this.t.push(this.formBuilder.group({...})
and which has controls
property).
So you can try to add another getter tControls
:
get f() { return this.dynamicForm.controls; }
get t() { return this.f.questions as FormArray; }
get tControls { return this.t.controls as FormGroup[]; }
and use it within *ngFor
:
<div *ngFor="let ticket of tControls; let i = index">
<div [formGroup]="ticket" class="form-row">
...
Please note, that now [formGroup]
will also be properly filled with FormGroup
and not AbstarctControl
One of your Angular upgrades probably added
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInputTypes": true,
}
to your tsconfig.json
file, you can verify it just by setting these values to false
and rebuilding your app, but I recommend to leave these strict checks.