1
votes

I'm trying to make form fields required on a Reactive Form but the form is always valid, I'd expect it to be invalid until both fields were not empty.

https://stackblitz.com/edit/angular-ivy-y4jby5?file=src/app/app.component.html

import { Component, VERSION, OnInit } from "@angular/core";
import {Form, FormArray, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  name = "Angular " + VERSION.major;
  testForm = this.fb.group({
    questions: this.fb.array([
      this.fb.group(
        [{testString: ['']}, Validators.required],
        [{testString: ['']}, Validators.required]
      )
    ])
  });
  
  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    const control = this.testForm.get('questions') as FormArray;
    control.push(this.fb.group(
      {
        testString: ['']
      }, Validators.required)
    )
  }

  get questionControls() {
     return this.testForm.get('questions') as FormArray;
  }
}
<form [formGroup]="testForm">
    <ng-container formArrayName="questions">
        <ng-container *ngFor="let question of questionControls.controls; let i = index">
            <input type="text" [formGroupName]="i">
        </ng-container>
    </ng-container>
</form>
Is Form Valid: {{ testForm.valid }}
2

2 Answers

1
votes

FormBuilder group method expect controlConfig as key-value pair, Where the key is the name of the FormControl and value is configuration of control.

In your example you are passing Invalid formControl configuration to formgroup that is why it's always valid. change the formGroup as follow.

component.ts

testForm = this.fb.group({
    questions: this.fb.array([
      this.fb.group({
        testString: ['',Validators.required]
      })
    ])
  });

Then In template we should bound testString key to formControlName directive like this:

<form [formGroup]="testForm">
    <ng-container formArrayName="questions">
        <ng-container *ngFor="let question of questionControls.controls; let i = index" [formGroupName]="i">
            <input type="text" formControlName="testString" >
        </ng-container>
    </ng-container> 
</form>

Working Example

0
votes

The way you set your formGroup inside your FormArray is wrong. You will need an object for your FormGroup See the example Below:
I also removed the ngOnInit Part.

    export class AppComponent {
      name = "Angular " + VERSION.major;
      testForm = this.fb.group({
        questions: this.fb.array([
          this.fb.group(
            {testString: new FormControl('', Validators.required)}
          ),
          this.fb.group(
            {testString: new FormControl('', Validators.required)}
          ),
        ])
      });
      
      constructor(private fb: FormBuilder) {}
      get questionControls() {
         return this.testForm.get('questions') as FormArray;
      }
    }

and for your HTML you will need a FormGroupName as well as FormControlName.
See the example below:

<form [formGroup]="testForm">
    <ng-container formArrayName="questions">
        <ng-container *ngFor="let question of questionControls.controls; let i = index">
          <ng-container [formGroupName]="i">
              <input formControlName="testString" />
            </ng-container>
        </ng-container>
    </ng-container>
</form>