Angular FormArray или FormGroup - с дополнительными данными
У меня есть таблица, которая создается динамически, и она отображает данные следующим образом:
<table>
<tr *ngFor="let product of products">
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>{{product.value}}</td>
<!-- BELOW IS WHERE A NEW VALUE WILL BE ENTERED -->
<td><input type="text" value=""></td>
</tr>
</table>
Я читал, что подходящим способом обработки этого является FormsArray. Но я также читал, что подходящий способ использования FormsArray - получить его массив элементов управления:
<table>
<tr *ngFor="let product of this.form.get('productCollection').controls; let i = index;"
[formGroupName]="i">
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>{{product.value}}</td>
<!-- BELOW IS WHERE A NEW VALUE WILL BE ENTERED -->
<td><input type="text" formControlName="name"></td>
</tr>
</table>
Проблема в том, что у меня нет доступа к значению описания здесь. И я не нашел способа передать это как метаданные в элемент управления, чтобы я мог показать это.
Таким образом, вопрос для чего-то вроде этого, какой правильный подход? Это FormArray? Это массив FormControls в одной FormGroup? Или каждый контроль формы должен быть сам по себе? Я открыт для предложений о том, как сделать эту работу.
2 ответа
В этом случае я бы перебрал реальный массив продуктов, а не массив элементов управления, поскольку вам нужно больше информации из данных, чем из элемента управления.
шаблон
<form [formGroup]="form">
<table formArrayName="productRows">
<tr *ngFor="let product of products; let i = index;" [formGroupName]="i">
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td><input type="text" formControlName="value"></td>
</tr>
</table>
</form>
Составная часть
buildForm() {
this.form = this.fb.group({
productRows: this.fb.array(this.initProductRows())
});
this.form.valueChanges.subscribe((change) => {
this.products.forEach((product, index) => {
product.value = change.productRows[index].value;
})
});
}
initProductRows() {
return this.products.map(product => {
return this.fb.group({
value: product.value
});
});
}
Частью ключа здесь является инициализация вашего массива FormArray в начале, когда вы строите форму такой же длины (и имеют те же значения), что и данные о продукте.
Кроме того, я не был уверен, пытаетесь ли вы сохранить новое значение обратно в исходные данные продукта, но если это так, то я добавил valueChanges
слушатель, чтобы вы могли написать это обратно. Смотрите все это в Stackblitz ниже.
Я думаю, я мог бы найти ответ. Ключ может состоять в том, чтобы НЕ делать FormArray, а скорее массив FormControls в FormGroup. Таким образом, я могу продолжать использовать список со всеми имеющимися у него данными, а затем добавить поле на основе FormGroup. Итак, конечный результат будет:
<table>
<tr *ngFor="let product of products">
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>{{product.value}}</td>
<!-- BELOW IS WHERE A NEW VALUE WILL BE ENTERED -->
<td>
<div formGroupName="productCollection">
<input type="text" formControlName="name">
</div>
</td>
</tr>
</table>
Если я ошибаюсь или у кого-то есть лучший путь, непременно покажи это и дай мне знать!