angularangular-reactive-formsangular-formsangular-formbuilder

How to set validators for a form control inside a formArray in angular


I'm trying to set a validator inside a formArray in angular and I don't know how to create it, my formGroup is

 itemsForm = this.fb.group({
    array: this.fb.array([this.fb.control(['']).setValidators(Validators.required)]),
  });

I tryed setting the validator inside the array but in the html it let me add another field without validated if this is empty or not my code is this:

HTML

<section [formGroup]="itemsForm" class="m-5">
  <section
    formArrayName="array"
    class="justify-content-center d-flex flex-wrap"
  >
    <div>
      <section class="d-flex flex-wrap">
        <div class="">
          <h4>Items Selected</h4>
        </div>
        <div class="">
          <button class="btn btn-primary" (click)="addItem()">Add Item</button>
        </div>
      </section>

      <section class="d-flex flex-column">
        <div
          class="form-group d-flex flex-row align-items-center"
          *ngFor="let item of itemsArray.controls; let index = index"
        >
          <h2 class="mr-2">item</h2>
          <input
            type="text"
            [formControlName]="index"
            class="form-control"
            [ngClass]="{
              'is-invalid': item.touched  && !item.valid
            }"
          />
        </div>
      </section>
    </div>
  </section>
</section>

TS

  @Input() defaultOption: string = '';
  @Input() optionsList: Array<string> = [];
  @Output() optionSelected = new EventEmitter<string>();

  selected: string = '';
  constructor(private fb: FormBuilder) {}
  itemsForm = this.fb.group({
    array: this.fb.array([this.fb.control(['']).setValidators(Validators.required)]),
  });


  get itemsArray(){
    return this.itemsForm.get('array') as FormArray
  }

  ngOnInit(): void {}

  updateSelection() {
    this.optionSelected.emit(this.selected);
  }
  addItem() {
    this.itemsArray.push(this.fb.control(''));
  }

Solution

  • try this...

      constructor(private fb: FormBuilder) {}
      itemsForm = this.fb.group({
        array: this.fb.array([this._createFormArrayControls()]),
      });
    
    
      get itemsArray(){
        return this.itemsForm.get('array') as FormArray
      }
    
      ngOnInit(): void {}
    
      private _createFormArrayControls(): FormControl{
       return this.fb.control('', Validators.required)
      }
    

    in the future, if you would need to initialize the form array to some default value based on an array you could then convert FormControl to FormGroup and do this:

    @Input() set items(value: Item[]) {
        itemsForm = this.fb.group({
        array: this.fb.array(value.map(i => this._createFormArrayGroup(i))),
      });
    };
      constructor(private fb: FormBuilder) {}   
        
      ngOnInit(): void {}
    
      private _createFormArrayGroup(item?: Item): FormGroup{   
       return this.fb.group({
        myItem: this.fb.control(item.Value, Validators.required)
       })
      }