I'm getting a problem with 'controls'enter image description here enter image description here "Object is possibly 'null'.ngtsc(2531)" and "Element implicitly has an 'any' type because type 'AbstractControl' has no index signature. Did you mean to call 'get'?ngtsc(7052)"
you can get an idea from this site https://csharp-video-tutorials.blogspot.com/2018/10/angular-dynamic-forms-tutorial.html what I want to do! I want to use formArray to check the validation. You can see below the picture whole hour input are displayed validation error. Because I didn't use formArray. when I implemented formArray It will get an error on this spot.
in the beginning I used this => *ngFor="let skill of employeeForm.get('skills').controls; let i = index" but the controls word is shown as an error!!!
.HTML
<form [formGroup]="employeeForm">
<div formArrayName="skills" *ngFor="let skill of employeeForm.get('skills')['controls']; let i = index;">
<div class="form-group">
<div class="col-sm-offset-2 col sm-4">
<button type="button" class="btn btn-primary" (click)="addSkillButtonClick()">ADD ROW</button>
</div>
</div>
<p-table [loading]="loading" styleClass="text-sm " [ngClass]="{'p-datatable-is-loading': loading}" [value]="dataSource"
[scrollable]="true" scrollHeight="calc(100% + 2px)" scrollDirection="both">
<ng-template pTemplate="header">
<tr>
<th style="width: 250px;">Project</th>
<th style="width: 250px;">Process</th>
<th style="width: 200px;">Working Hours</th>
<th alignFrozen="right" pFrozenColumn class="p-frozen-column p-frozen-border-left" style="width: 114px;"></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-source let-index="rowIndex">
<tr *ngIf="dataSource[index].editing; else viewingMode;" class="editing editing-mode" formGroupName="0">
<td style="width: 250px; overflow: visible" >
<div>
<p-autoComplete appendTo="body" #project name="project" [(ngModel)]="dataSource[index].project_id" [suggestions]="projectSuggestions"
field="name" (onSelect)="handleSelectProject($event, index)"
formControlName="project" class="form-control"
(completeMethod)="handleSearchProject($event, index)" (onFocus)="project.show()" placeholder="Search project">
</p-autoComplete>
</div>
</td>
<td style="width: 250px;">
<div>
<p-dropdown formControlName="process" name="process" [ngStyle]="{ width: '100%' }" [(ngModel)]="dataSource[index].process" [options]="processOptions"
placeholder="Select process">
</p-dropdown>
</div>
</td>
<td style="width: 200px;" class="drg-table_working_hours">
<div ngClass="{'has-error': formErrors.hours }">
<p-inputNumber formControlName="hours" [(ngModel)]="dataSource[index].hour" [id]="'working_hour'+ index" [name]="'working_hour'+ index" [min]="0" [max]="24"
placeholder="00" (blur)="logValidationErrors"></p-inputNumber>
<label for="hours" class="md-2 mb-0 pb-0 mr-2 ml-2">h</label>
</div>
<div>
<p-inputNumber formControlName="minutes" [(ngModel)]="dataSource[index].minutes" [id]="'working_min'+ index" [name]="'working_min'+ index" [min]="0" [max]="59" placeholder="0" ></p-inputNumber>
</div>
<label for="hours" class="md-2 mb-0 pb-0 mr-2 ml-2">m</label>
</td>
<td alignFrozen="right" class="flex-row-reverse p-frozen-column p-frozen-border-left" pFrozenColumn style="width: 114px;">
<button [disabled]="dataSource[index].deleting" pButton type="button" (click)="handleDeleteRowClick(index)" icon="pi pi-trash"
class="p-button-link p-button-plain p-button-rounded p-button-outlined"></button>
<button pButton type="button" (click)="handleSaveRowClick(index)" icon="pi pi-save"
class="p-button-link p-button-plain p-button-rounded p-button-outlined mr-1"></button>
</td>
</tr>
</ng-template>
</p-table>
</div>
</form>
.TS
export class DailyReportRegularTableComponent extends DailyReportLog implements OnInit {
@Input() dataSource: UIDailyLogRegularTableInterface[] = [];
@Output() dataSourceChange = new EventEmitter<UIDailyLogRegularTableInterface[]>();
helper!: HelperService
_formHelper: FormService = new FormService;
employeeForm!: FormGroup;
formErrors: any;
validationMessages: any;
constructor(private _helper: HelperService,private formBuilder: FormBuilder,private fb: FormBuilder) {
super();
this.helper = this._helper;
}
ngOnInit(): void {
this.employeeForm = this.fb.group({
skills: this.fb.array([
this.addSkillFormGroup()
])
});
this.employeeForm.valueChanges.subscribe((data) => {
this.logValidationErrors(this.employeeForm)
});
}
addSkillButtonClick(): void {
(<FormArray>this.employeeForm.get('skills')).push(this.addSkillFormGroup());
}
logValidationErrors(group: FormGroup = this.employeeForm): void{
Object.keys(group.controls).forEach((key: string) =>{
const abstractControl = group.get(key)
if(abstractControl instanceof FormGroup){
this.logValidationErrors(abstractControl)
} else {
this.formErrors[key] = '';
if(abstractControl && !abstractControl.valid){
for (const errorKey in abstractControl.errors) {
if (errorKey) {
this.formErrors[key];
}
}
}
if (abstractControl instanceof FormGroup) {
this.logValidationErrors(abstractControl);
}
if (abstractControl instanceof FormArray) {
for (const control of abstractControl.controls){
if (control instanceof FormGroup) {
this.logValidationErrors(control)
}
}
}
}
})
}
addSkillFormGroup(): FormGroup{
return this.fb.group({
project: ['', Validators.required],
process: ['', Validators.required],
hours: ['', Validators.required],
minutes: [''],
})
}
OnLoadDataClick(): void{
this.logValidationErrors(this.employeeForm)
}
}