-1

I have a form group which has an array of custom form controls (Custom form control also has validation). Whenever I push a new form control to the array, the validation for the complete form is not run properly.

It seems that when a new form control is pushed, validation for the parent form control is run first and then only does validation for the child form control run. Does anyone have any ideas as to why?

Please refer to the stackblitz link at https://stackblitz.com/edit/angular-fh6vzw?embed=1&file=src/app/app.component.ts

Lilylakshi
  • 736
  • 7
  • 19

1 Answers1

0

You need give a breath to Angular, just in your function onAddHero, add a setTimeout(()=>heroesArray.updateValueAndValidity()

onAddHero() {
    const heroesArray = this.formGroup.get('heroes') as FormArray;
    heroesArray.push(new FormControl({
      name: '',
      wealth: ''
    }));
    //this lines
    setTimeout(()=>{
        heroesArray.updateValueAndValidity()
    })
    console.log('hero added');
  }

BTW, I think that is a "bizarro" way to do the things, for me is more simple create components with @Input and @Ouput and manage the form from the app.component

That's, our app.component

<form [formGroup]="newForm" (submit)="onSubmit()">
    <div class="form-group">
        <label>Collection name<input formControlName="collectionName" class="form-control" /></label>
    </div>
    <app-comic-book [form]="newForm.get('comicBook')" (addHero)="addHero()"></app-comic-book>
    <button type="submit" [disabled]="!newForm.valid" class="btn btn-primary">Submit</button>
</form>
  newForm: FormGroup = this.fb.group({
    collectionName: 'classics 1',
    comicBook: this.fb.group({
      name: 'volume 1',
      heroes: this.fb.array([
        this.createHeroe({
          name: 'Superman',
          wealth: 'Piss poor'
        }),
        this.createHeroe({
          name: 'Batman',
          wealth: 'Crazy rich'
        })
      ])
    })
  });

  constructor(private fb: FormBuilder) { }

  createHeroe(data)
  {
    data=data || {name:'',wealth:''}
    return this.fb.group({
      name:[data.name,Validators.required],
      wealth:[data.wealth,Validators.required]
    })
  }
  addHero()
  {
    const heroes=this.newForm.get('comicBook.heroes') as FormArray;
    heroes.push(this.createHeroe(null))
  }
  onSubmit() {
    console.log(this.newForm);
  }

Our comic-book.component

<div [formGroup]="formGroup">
    <div class="form-group">
        <label>Comicbook name<input formControlName="name" class="form-control" /></label>
    </div>
    <div formArrayName="heroes">
        <div *ngFor="let hero of formGroup.get('heroes').controls; let i = index">
            <app-hero [form]="hero"></app-hero>
        </div>
    </div>
  <button (click)="onAddHero()" class="btn btn-primary">Add Hero</button>
</div>

export class ComicBookComponent {
  @Input('form')formGroup
  @Output()addHero = new EventEmitter<any>();
  onAddHero()
  {
    this.addHero.emit()
  }
}

And our hero-component

<div [formGroup]="formGroup">
    <div class="form-group">
        <label>Hero name<input formControlName="name" class="form-control" /></label>
    </div>

    <div class="form-group">
        <label>Hero wealth<input formControlName="wealth" class="form-control" /></label>
    </div>
</div>

export class HeroComponent  {
  @Input('form')formGroup
}
Eliseo
  • 50,109
  • 4
  • 29
  • 67