简体   繁体   中英

Making FormArray controls required on Reactive Form

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 }}

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

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM