0

I have used formArray and now Iam doing validation on the array fields. Below is my code but when I click on Submit, I am getting

ERROR TypeError: Cannot read property 'errors' of undefined.

and the first line of html is highlighted in red on console. Please let me know the actual cause.

app.component.html

  <div *ngFor="let items of contractList.controls; let i=index" 
                [formGroupName]="i">
    <table>
    <thead></thead>
    <tbody>
    <tr> 
     <td>
        <div class="form-group col-xs-6">
          <label for="copay">Copay Amount:</label>
          <input formControlName="copay" placeholder="Copay Amount" class="form-control" name="copay" id="copay" [ngClass]="{ 'is-invalid': submitted && items.get('copay').errors }">
        <div *ngIf="submitted && items.get('copay').errors" class="invalid-feedback">
                                <div *ngIf="items.get('copay').errors.required">Copay is required</div>
                            </div>
        </div>
        </td>

app.component.ts

 get contractList() {
         return this.addForm.get('contractServiceList') as FormArray;
      }
      constructor(public formBuilder: FormBuilder, public router:
        Router, public activatedRoute: ActivatedRoute, public contractService: ContractService) {
      }
    get f() { return this.addForm.controls; }

       arrayValidator() {
        return (control: FormArray) => {
          return null;
         }
      }
      createForm(data: any): FormGroup {
        return this.formBuilder.group({
          contractName: [data ? data.contractName : '', Validators.required],
          contractServiceList: this.formBuilder.array(
                 this.createContractService(data ? data.contractServiceList : null),this.arrayValidator()
                  )
          });
      }
      createContractService(data: any[]|null): FormGroup[] {
        return data ?
          data.map(x => {
            let group = this.formBuilder.group({
              serviceId: [x.serviceId, Validators.required],
              copay: [x.copay, Validators.required],
              coinsurance: [x.coinsurance, Validators.required],
              deductibleApplies: [x.deductibleApplies, Validators.required],
              penaltyApplies: [x.penaltyApplies, Validators.required],
              penaltyRule: [x.penaltyRule, Validators.required],
              penaltyType: [x.penaltyType, Validators.required],
              penaltyValue: [x.penaltyValue, Validators.required],
              deductibleAppliesPenalty: [x.deductibleAppliesPenalty, Validators.required]
                });
            return group;
          }) :
          [this.formBuilder.group(
            {
              serviceId: ['', Validators.required],
              copay: ['', Validators.required],
              coinsurance: ['', Validators.required],
              deductibleApplies: ['', Validators.required],
              penaltyApplies: ['', Validators.required],
              penaltyRule: ['', Validators.required],
              penaltyType: ['', Validators.required],
              penaltyValue: ['', Validators.required],
              deductibleAppliesPenalty: ['', Validators.required]
            })];
      }
      ngOnInit() {
         {
        this.addForm = this.createForm(null);
      }
      }

      onSubmit() {
        this.submitted = true;
        console.log(this.addForm.value);
        if (this.addForm.invalid) {
                return;
            }
        this.contractService.saveContract(this.addForm.value)
          .subscribe( data => {
            if ( window.confirm('Contract created successfully') ) {
              this.addForm.reset();
            }

1 Answer 1

1

Try something like this:

Using Array Index here to get controls of form array

I assumed form as addForm and formarray as contractServiceList

addForm.controls.contractServiceList.controls[i].controls.copay.errors

Or

addForm.controls.contractServiceList['controls'][i].get('copay').errors

HTML:

<div *ngFor="let items of contractList.controls; let i=index" [formGroupName]="i">
    <table>
        <thead></thead>
        <tbody>
            <tr>
                <td>
                    <div class="form-group col-xs-6">
                        <label for="copay">Copay Amount:</label>
                        <input formControlName="copay" placeholder="Copay Amount" class="form-control" name="copay" id="copay">
                        <div *ngIf="addForm.controls.contractServiceList.controls[i].controls.copay.errors.required">Copay is required</div>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
</div>
Sign up to request clarification or add additional context in comments.

5 Comments

It worked for me but I get a bug in my code that when I am going with a positive flow, the form is submitted and at last I am resetting the form. So on reset, the validation red error message comes which ideally should not happen. Validation should only come when I am clicking on Submit button. this.contractService.saveContract(this.addForm.value) .subscribe( data => { if ( window.confirm('Contract created successfully') ) { this.addForm.reset(); } }); This is the code for submit which I am using, let me know if there is something to be changed.
set control to touched/untouched to hide/show red mark
This is not the bug just some change are required.
If not working create stackblitz example stackblitz.com i will update your solution
Could you please add touched/untouched line of code into this piece and guide me how to add <input ...... [ngClass]="{ 'is-invalid': submitted && addForm.controls.contractServiceList.controls[i].controls.copay.errors }"> <div *ngIf="submitted && addForm.controls.contractServiceList.controls[i].controls.copay.errors" class="invalid-feedback"> <div *ngIf="addForm.controls.contractServiceList.controls[i].controls.copay.errors.required">Copay is required</div> </div>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.