web-dev-qa-db-fra.com

Comment obtenir l'index d'un élément modifié dans un tableau de forme angulaire

J'utilise Angular 4 avec des formes réactives. J'essaie de lier un tableau de formulaire à un tableau que je garde dans mon composant. J'utilise des formulaires réactifs pour que je puisse avoir la validation, donc je ne veux pas utiliser l'approche des formulaires modèles.

J'ajoute des éléments au tableau de formulaire comme suit:

createFormWithModel() {
  this.orderForm = this.fb.group({
    orderNumber: [this.order.ProductBookingOrder],
    orderDate: [this.order.PurchaseOrderIssuedDate],
    lineDetailsArray: this.fb.array([])
  })

  const arrayControl = <FormArray>this.orderForm.controls['lineDetailsArray'];
  this.order.ProductBookingDetails.forEach(item => {
    let newGroup = this.fb.group({
      ProductName: [item.ProductName],
      Quantity: [item.ProductQuantity.Quantity],
      UOM: [item.ProductQuantity.UOM],
      RequestedShipDate: [item.RequestedShipDate]
    })
  })
}

Le orderForm est évidemment mes formes réactives FormGroup. la commande est mon objet que je reçois de mon API et je souhaite mettre à jour ses valeurs, y compris les détails de la ligne. Je pense que je devrais utiliser 'valueChanges.subscribe' sur chaque nouveau groupe, mais je ne sais pas comment obtenir l'index de l'élément qui a été modifié. Des pensées?

     newGroup.valueChanges.subscribe('i want value and index some how' => {
this.order.ProductbookingDetails[index].ProductName = value.ProductName;
    });

Voici le code HTML pour cette partie:

<tbody formArrayName="lineDetailsArray">
        <tr [formGroupName]="i" *ngFor="let line of orderForm.controls['lineDetailsArray'].controls; index as i">
          <td><input class="form-control" type="text" placeholder="Product Name" formControlName="ProductName" required/></td>
          <td><input class="form-control" type="number" step=".01" (focus)="$event.target.select()" placeholder="Quantity" formControlName="Quantity"/></td>
          <td><input class="form-control" readonly formControlName="UOM"></td>
          <td><date-picker formControlName="RequestedShipDate" format="L" [showClearButton]="false"></date-picker></td>
          <td><button type="button" (click)="deleteLineDetail(i)">Remove</button></td>
        </tr>
      </tbody>
8
Kevin

Je ne voudrais pas utiliser la valueChanges ici, il serait déclenché de manière excessive, spécialement si le tableau a beaucoup de valeurs.

Vous pouvez avoir un événement change sur chaque valeur et simplement passer la valeur et l’index, quelque chose comme

(keyup)="changeValue(line.controls.ProductName.value, i)"

Mais ce genre de lutte contre le but de la forme réactive. 

Même si vous avez beaucoup de valeurs que vous ne voulez pas afficher dans le formulaire, et que ce sont des valeurs que l'utilisateur ne peut pas modifier, je les ajouterais quand même au formulaire en tant que contrôles de formulaire, rien ne dit que vous deviez les afficher dans modèle!

Ainsi, si vous construisez le formulaire de manière à ce qu'il corresponde à votre modèle order, vous pouvez simplement affecter directement la valeur du formulaire à votre modèle lors de la soumission. Je recommande fortement cette approche.

7
AJT_82
export class CustomFormArray {
     public form: FormGroup;

     public get someArray(): FormArray {
          return this.form.get('someArray') as FormArray
     }

     constructor(private _fb: FormBuilder) {
          this.form = _fb.group({
               someArray: _fb.array([])
          });

          this.someArray.controls.forEach(
               control => {
                   control.valueChanges.subscribe(
                        () => {
                       console.log(this.someArray.controls.indexOf(control)) // logs index of changed item in form array
                        }
                   )
               }
          )
     }
}    
4
Ivan Tkachyshyn

Vous pouvez créer un propre composant pour les éléments que vous souhaitez gérer dans votre tableau de formulaire. Pour chaque mise à jour, supprimez, etc., vous émettez un événement au composant parent et l’index que vous pouvez émettre avec l’événement auquel vous êtes lié dans le composant parent, ou vous avez l’index dans le composant parent dans le modèle pour pouvoir l’utiliser comme paramètre d'entrée supplémentaire pour la fonction que vous utilisez pour lier l'événement de modification du composant enfant.

Lisez cet article et vous comprendrez ce que je veux dire:

https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4

0
Gerros