I would utilize a form and formarray, besides, what you have now, is one single formcontrol for your whole array, so I cannot see how it works for your array.
Also, the validator you have written is basically a required validator, so you could use the inbuilt validator for that. So I suggest the following:
I have hardcoded _Computers array, I build the form, I loop the _Computers and add formcontrols to the formarray. Based on the Optional property I set Validators.required for the unit price only for those that the Optional value is false. Here I am pushing 2 formcontrols to each formgroup in the array, the name and the unitOfPrice, you can push any amount you want.
I make a getter for the formarray, just for easier access. All in all, code would look like this:
_Computers = [
{ Name: 'name1', Optional: true, UnitOfPrice: null },
{ Name: 'name2', Optional: false, UnitOfPrice: null },
];
myForm!: FormGroup;
constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
computers: this.fb.array([]),
});
this._Computers.forEach((x: any) => {
if (x.Optional) {
this.computersArr.push(this.fb.group({
name: [x.Name],
unitOfPrice: [null]
}));
} else {
this.computersArr.push(this.fb.group({
name: [x.Name],
unitOfPrice: [null, [Validators.required]]
}));
}
});
}
get computersArr() {
return (this.myForm.get('computers') as FormArray).controls;
}
I have been lazy and used any here, please type your data instead!
The template would then show the form, and we can display a message of required if it has such a validator:
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div formArrayName="computers">
<div *ngFor="let computer of computersArr; let i = index">
<div [formGroupName]="i">
<label>{{computer.get('name').value}}</label>
<input formControlName="unitOfPrice" />
<small *ngIf="computer.get('unitOfPrice').hasError('required')">Required!!</small>
</div>
</div>
</div>
</form>
Above is using div's but you can easily replicate the same for a table.
Here is a STACKBLITZ for your reference.