ERROR TypeError: Cannot read property 'errors' of null angular form not seeing the nested FormBuilder group

The nested form group is not readable for html file!

this.addSaleForm = this.formBuilder.group({
      storeId: ['', [Validators.required]],
      clientId: ['', [Validators.required]],
      saleDateTime: ['', [Validators.required]],
      amountPaid: ['', [Validators.required, Validators.minLength(1)]],
      invoice: this.formBuilder.group({
        discount: ['', [Validators.required, Validators.min(0), Validators.max(100)]],
        description: ['', [Validators.minLength(4), Validators.maxLength(250)]],
        serial: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(10)]],
        signture: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(50)]],
      })
    });

html of the component couldn't read invoice as a formGroupName although that the rest of for controls is readable without problem!

<div [formGroupName]="invoice">
      <!-- Row of Serial & Signture & DateTime -->
      <div class="form-row">
        <!-- Serial Form Group -->
        <div class="col mb-3">
          <input
            type="number"
            [ngClass]="{
              'is-invalid':
                addSaleForm.get('serial').errors &&
                addSaleForm.get('serial').touched
            }"
            class="form-control"
            formControlName="serial"
            placeholder="Serial"
          />
          <div
            class="invalid-feedback"
            *ngIf="
              addSaleForm.get('serial').hasError('required') &&
              addSaleForm.get('serial').touched
            "
          >
            Invoice Serial is required
          </div>
        </div>
  </div>
</div>

1 answer

  • answered 2019-10-08 04:08 developer033

    html of the component couldn't read invoice as a formGroupName although that the rest of for controls is readable without problem!

    The problem is that you're using property binding for formGroupName ([formGroupName]) where you should use simply formGroupName.


    To access the nested control serial you can do the following:

    [ngClass]="{
      'is-invalid':
        addSaleForm.get('invoice.serial').errors &&
        addSaleForm.get('invoice.serial').touched
    }"
    
    *ngIf="
      addSaleForm.get('invoice.serial').hasError('required') &&
      addSaleForm.get('invoice.serial').touched
    "
    
    ... or even better IMHO:
    
    *ngIf="
      addSaleForm.hasError('required', 'invoice.serial') &&
      addSaleForm.get('invoice.serial').touched
    "
    

    Full template (with a little refactor -- using [class] binding and the "as" syntax to create a reference for the serial form control):

    <div formGroupName="invoice">
      <!-- Row of Serial & Signture & DateTime -->
      <div class="form-row">
        <!-- Serial Form Group -->
        <div class="col mb-3" *ngIf="addSaleForm.get('invoice.serial') as serialFormControl">
          <input
            type="number"
            [class.invalid]="serialFormControl.errors && serialFormControl.touched"
            class="form-control"
            formControlName="serial"
            placeholder="Serial"
          />
          <div
            class="invalid-feedback"
            *ngIf="serialFormControl.hasError('required') && serialFormControl.touched"
          >
            Invoice Serial is required
          </div>
        </div>
      </div>
    </div>