1
votes

Comment remplir une valeur pour FormArray à l'aide de la méthode de contrôle set?

J'ai un formulaire réactif avec le champ de saisie dynamique. J'ai généré ces champs avec FormArray . Maintenant, j'essaie de préremplir le formulaire avec des données sur l'écran d'édition, mais je n'ai pas pu le faire. J'ai essayé de remplir en utilisant la méthode setControl J'ai eu cette erreur Impossible de trouver le contrôle avec le chemin: 'books -> 0 -> name'

Voici les sources que j'ai prises pour référence

  1. https://alligator.io/angular/reactive-forms- formarray-dynamic-fields /
  2. https://stackoverflow.com/a/44988197/9715025
  3. https://stackoverflow.com/a/42599327/9715025

<form [formGroup]="formGroup">
  <div formArrayName="books" *ngFor="let book of formGroup.get('books')['controls']; let i = index;">
    <div class="row" [formGroupName]="i">
      <input type="text" autocomplete="off" placeholder="*Name"
      formControlName="name">
      <input type="text" autocomplete="off" placeholder="*Author"
      formControlName="author">
      <button type="button" class="btn btn-success" (click)="addBook();">Add</button>
    </div>
  </div>
</form>

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, FormArray } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

export interface ServerResponse {
  books: any;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  formGroup: FormGroup;
  books: FormArray;

  constructor(
    private http: HttpClient,
    private formBuilder: FormBuilder,
  ) {

  }

  createForm() {
    this.formGroup = this.formBuilder.group({
      books: this.formBuilder.array([this.createBookForm()]),
    });
  }

  createBookForm() {
    return this.formBuilder.group({
      name: [],
      author: [],
    });
  }

  addBook() {
    this.books = this.formGroup.get('books') as FormArray;
    this.books.push(this.createBookForm());
  }

  getData(): Observable<ServerResponse> {
    return this.http.get<ServerResponse>('https://demo0331989.mockable.io/library/data/book');
  }

  populateData() {
    this.getData().subscribe(data => {
      this.formGroup.setControl('books', this.formBuilder.array(data.books || []));
    });
  }

  ngOnInit() {
    this.createForm();
    this.populateData();
  }
}

Je partage également le code dans Stackblitz . Échantillon / simulation de données à pré-remplir. Je ne suis pas sûr de ce qui me manque ici!


0 commentaires

3 Réponses :


0
votes

J'ai fait un fork de votre exemple stackblitz , alors jetez un œil. Lorsque vous souhaitez pré-remplir votre formulaire, vous devez créer BookForm et le passer dans setControl, pas seulement dans un tableau.


0 commentaires

1
votes

lorsque vous remplissez un tableau de formulaire, vous devez le remplir avec des groupes de formulaires remplis, de sorte que cela ressemble à ceci:

populateData() {
  this.getData().subscribe(data => {
    const books = this.formGroup.get('books') as FormArray; // get the array
    books.clear(); // clear the array 
    data.books.forEach(b => { // iterate data
      let fg = this.createBookForm(); // create the group
      fg.reset(b); // fill the data
      books.push(fg); // add to array
    });
    this.addBook(); // add blank form to end if desired
  });
}

la suppression de la partie du formulaire / l'ajout du blanc au end peut ou non être nécessaire.

voici un blitz fixe: https://stackblitz.com/edit/angular-9ts4yv?file=src/app/app.component.ts


0 commentaires

1
votes

avertissement cette réponse est complémentaire de la réponse @ bryan60,

J'aime ma fonction createBookForm a comme argument "data", donc

  populateData() {
    this.getData().subscribe(data => {
      const books = this.formGroup.get('books') as FormArray;
      books.clear();
      data.books.forEach(b => {
        books.push(this.createBookForm(b))
      });
    });
  }

Cela nous permet d'écrire

createBookForm(null) //create a FormGroup with name and author and values null
//or 
createBookForm({name:"Linus Administration",author:"Roger"}) //the formgroup has values

Notre fonction populateData devient plus simple

createBookForm(data:any) {
    data=data||{name:null,author:null}
    return this.formBuilder.group({
      name: data.name,
      author: data.author,
    });
  }

REMARQUE: je ne vois pas le nécésité de déclarer un formGroup avec une propriété unique qui est un FormArray, voir ma réponse entre autres dans question stackoverflow


1 commentaires

Ça marche! Eh bien, explication claire. Merci.