J'essaie d'implémenter un formulaire d'édition pour un modèle avec des attributs imbriqués (FormArray). J'ai des problèmes avec la syntaxe et je ne sais pas si je suis sur la bonne voie. Les attributs du formulaire principal fonctionnent, c'est le formulaire imbriqué avec lequel j'ai des problèmes. Voici ce que j'ai jusqu'à présent.
Ici, j'initie le groupe de formulaires:
private initForm() {
this.subscription = this.expenseService.getExpense(this.id)
.subscribe(
expense => {
this.expense = expense;
this.patchForm();
}
);
this.expenseEditForm = this.fb.group({
date: '',
amount: '',
check_number: '',
debit: '',
payee_id: '',
notes: '',
expense_expense_categories_attributes:[]
});
}
Ici, je corrige le formulaire pour définir les valeurs d'un objet récupéré de mon API backend.
private patchForm() {
this.expenseEditForm.setValue({
date: '',
amount: this.expense.amount_cents,
check_number: this.expense.check_number,
debit: this.expense.debit,
payee_id: '',
notes: this.expense.notes,
expense_expense_categories_attributes: this.fb.array([
this.setExpenseCategories(),
])
});
}
C'est là que je suis coincé. Comment puis-je pousser sur un FormArray. Si j'essaie de pousser, j'obtiens une erreur indiquant que Push n'existe pas sur FormArray.
private setExpenseCategories() {
for ( let expenseCategories of this.expense.expense_expense_categories){
this.fb.array.Push([
this.fb.group({
expense_category_id: [expenseCategories.expense_category_id, Validators.required],
amount: [expenseCategories.amount_cents]
])
});
}
}
Juste au cas où cela serait nécessaire. Voici mon html.
<div
*ngFor="let expensecategoriesCtl of expenseEditForm.controls.expense_expense_categories_attributes.controls let i = index"
[formGroupName]="i"
style="margin-top: 10px;">
<md-card>
<md-select class="full-width-input"
placeholder="Expense Category"
id="expense_category_id"
formControlName="expense_category_id"
>
<md-option *ngFor="let expenseCategory of expenseCategories" value="{{expenseCategory.id}}">
{{expenseCategory.category}}
</md-option>
</md-select>
<md-input-container class="full-width-input">
<input
mdInput placeholder="Amount"
type="number"
formControlName="amount">
</md-input-container>
</md-card>
</div>
Quelques changements dans la réponse de DeborahK, puisque expense.expense_expense_categories
ne contient pas de types primitifs, mais des objets. Par conséquent, nous ne pouvons pas affecter les valeurs telles quelles, mais chaque objet doit être enveloppé dans un FormGroup
, comme vous l'avez tenté.
Ici, j'ai une version abrégée de votre code:
Créez le formulaire:
ngOnInit() {
this.expenseEditForm = this.fb.group({
notes: [''],
// notice below change, we need to mark it as an formArray
expense_expense_categories_attributes: this.fb.array([])
})
Ensuite, nous appelons patchForm
dans le rappel, tout comme vous l'avez fait. Cette fonction ressemblerait à ceci, remarquez, nous appelons this.setExpenseCategories
à l'extérieur:
patchForm() {
this.expenseEditForm.patchValue({
notes: this.expense.notes,
})
this.setExpenseCategories()
}
Vient ensuite le plus grand changement par rapport à votre code existant, où nous attribuons d'abord le FormArray
à la variable control
puis nous itérons votre tableau reçu du backend, créons un FormGroup
pour chaque objet et pousser l'objet à chaque FormGroup
:
setExpenseCategories(){
let control = <FormArray>this.expenseEditForm.controls.expense_expense_categories_attributes;
this.expense.expense_expense_categories.forEach(x => {
control.Push(this.fb.group(x));
})
}
Ensuite, pour le modèle, cet exemple est sans Angular Material:
<form [formGroup]="expenseEditForm">
<label>Notes: </label>
<input formControlName="notes" /><br>
<!-- Declare formArrayName -->
<div formArrayName="expense_expense_categories_attributes">
<!-- iterate formArray -->
<div *ngFor="let d of expenseEditForm.get('expense_expense_categories_attributes').controls; let i=index">
<!-- Use the index for each formGroup inside the formArray -->
<div [formGroupName]="i">
<label>Amount: </label>
<input formControlName="amount" />
</div>
</div>
</div>
</form>
Enfin un
Si je comprends bien votre question, vous aurez peut-être besoin de quelque chose comme ceci:
// Update the data on the form
this.productForm.patchValue({
productName: this.product.productName,
productCode: this.product.productCode,
starRating: this.product.starRating,
description: this.product.description
});
this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
Vous pouvez voir l'exemple complet ici: https://github.com/DeborahK/Angular2-ReactiveForms dans le dossier APM - Updated.