[Fixed] Problem with validatons inside a FormArray

Issue

I am new to angular and I am currently building a website in angular, Im facing a problem that I cant solve with the angular documentation Im not quite understanding what’s going on behind the problem.

In few words, I have a formArray(updateAddress) which contains a formGroup and some formControl’s inside and I’m having a hard time trying to make the validations for it.

Code HTML:

<form [formGroup]="profileForm">
<div *ngFor="let add of updateAddress().controls; let addIndex=index">
    <div formArrayName="updateAddress">
      <div [formGroupName]="addIndex">
        <label>
          Rua:
          <input type="text" formControlName="address">
        </label>
        <div
          *ngIf="profileForm.get('add.address')?.invalid && (address.get('add.address')?.dirty || profileForm.get('add.address')?.touched)">
          <div *ngIf="profileForm.get('add.address')?.errors?.required">
            Tem de escrever a rua da sua loja.
          </div>
        </div>
<button (click)="removeAddress(addIndex)">Remover</button>
      </div>
    </div>
  </div>
  <button type="button" (click)="addAddress()">Adicionar Morada</button>
</form>

Code TS:

  profileForm: FormGroup;

  control: any;

  
  constructor(
              public formBuilder: FormBuilder,
              private cd: ChangeDetectorRef
             ) {

    this.profileForm = this.formBuilder.group({
      file: [''],
      name: new FormControl('', [Validators.required, Validators.pattern('[a-zA-Z ]*')]),
      email: new FormControl('',  [Validators.required, Validators.pattern("^[a-z0-9._%+-][email protected][a-z0-9.-]+\\.[a-z]{2,4}$")]),
      password: new FormControl('',[Validators.required, Validators.minLength(7),Validators.pattern('(?=.*[A-Za-z])(?=.*[0-9])(?=.*[[email protected]$!#^~%*?&,.<>"\'\\;:\{\\\}\\\[\\\]\\\|\\\+\\\-\\\=\\\_\\\)\\\(\\\)\\\`\\\/\\\\\\]])[A-Za-z0-9\[email protected]].{7,}')]),
      password2: new FormControl('', Validators.required),
      nif: new FormControl('',[Validators.required, Validators.pattern('\\d{9}')]),
      birthDate: new FormControl('',[Validators.required, Validators.pattern("^(0[1-9]|[12][0-9]|3[01])[/.](0[1-9]|1[012])[/.](19|20)\\d\\d$") ]),
      phoneNumber: new FormControl('', [Validators.required, Validators.pattern('\\d{9}')]),
      updateAddress: new FormArray([], Validators.required)
    });
   }

  updateAddress(): FormArray {
        return this.profileForm.get("updateAddress") as FormArray
  }

  newAddress(): FormGroup {
      return this.formBuilder.group({
        address: new FormControl('', Validators.required),
        address2: new FormControl('', Validators.required),
        postalCode: new FormControl('', Validators.required),
        city: new FormControl('', Validators.required),
        area: new FormControl('', Validators.required)
      })
  }

  addAddress() {
      this.updateAddress().push(this.newAddress());
  }
  
  removeAddress(addIndex:number) {
    this.updateAddress().removeAt(addIndex);
  }

I really cant solve the problem in this validation because the validation feels like it goes through but doesnt appear any error in the webpage also I dont know if Im approaching this the right way or not aswell.

image comproving the validation is working because submit is disabled but not sending a error when it should send under the "Rua" input

If someone can guide me or help I’ll gladly appreciate it!

UPDATE

As I said I think the validation works on the background but the error text that should appear just doesnt appear because Im not getting the ngIf right(I think)

Solution

Some items to note

You can initiate your form like below using FormBuilder

    this.profileForm = this.formBuilder.group({
      file: [''],
      name: ['', [Validators.required, Validators.pattern('[a-zA-Z ]*')]],
      email: ['',  [Validators.required, Validators.pattern("^[a-z0-9._%+-][email protected][a-z0-9.-]+\\.[a-z]{2,4}$")]],
      password: ['',[Validators.required, Validators.minLength(7),Validators.pattern('(?=.*[A-Za-z])(?=.*[0-9])(?=.*[[email protected]$!#^~%*?&,.<>"\'\\;:\{\\\}\\\[\\\]\\\|\\\+\\\-\\\=\\\_\\\)\\\(\\\)\\\`\\\/\\\\\\]])[A-Za-z0-9\[email protected]].{7,}')]],
      password2: ['', Validators.required],
      nif: ['',[Validators.required, Validators.pattern('\\d{9}')]],
      birthDate: ['',[Validators.required, Validators.pattern("^(0[1-9]|[12][0-9]|3[01])[/.](0[1-9]|1[012])[/.](19|20)\\d\\d$") ]],
      phoneNumber: ['', [Validators.required, Validators.pattern('\\d{9}')]],
      updateAddress: this.formBuilder.array([], Validators.required)
    });

    newAddress(): FormGroup {
      return this.formBuilder.group({
        address: ['', Validators.required],
        address2: ['', Validators.required],
        postalCode: ['', Validators.required],
        city: ['', Validators.required],
        area: ['', Validators.required]
      })
  }

You can alse change updateAddress to a getter

  get updateAddress(): FormArray {
    return this.profileForm.get("updateAddress") as FormArray
  }

To the problem

I believe the problem is in how you are trying to retrieve the errors

Try to use formGroup.get('control_name').errors in your case, the validation is applied to the controls inside the formArray so we need to access this and get the errors, something like

add.get('address').errors?.required

Below is a sample html.

  <ng-container formArrayName="updateAddress">
    <div *ngFor="let add of updateAddress.controls; let addIndex=index">
      <div [formGroupName]="addIndex">
        <label>
          Rua:
          <input type="text" formControlName="address">
        </label>

        <div *ngIf="add.get('address').invalid && (add.get('address').dirty || add.get('address').touched)">
          <div *ngIf="add.get('address').errors?.required">
            Tem de escrever a rua da sua loja.
          </div>
        </div>
        <button (click)="removeAddress(addIndex)">Remover</button>
      </div>
    </div>
    <button type="button" (click)="addAddress()">Adicionar Morada</button>
  </ng-container>

You can have a look at This stackblitz demo

Edit

To initializa value for the form you can use setValue or patchValue. Something like below

   this.updateAddress.at(0).setValue({
      address: "My Address",
      address2: "My Address 2",
      postalCode: "77777",
      city: "Helsinki",
      area: "Some street"
    });

See this demo

Leave a Reply

(*) Required, Your email will not be published