Reputation: 81
I'm little confused about how I should work with Angular 2 when I need <input>
tags inside the <tr>
tags of a table, when the <tr>
tags are generated by a *ngFor
. My situation is this: I have an array of "products", I should show the product's info on <tr>
tags and, for each product, an input
field to increase the stock of each product. This is what I have done:
export class ProductStokeComponent implements OnInit {
form: FormGroup;
products: Subject<Product[]> = new Subject();
constructor(
private productService: ProductService,
private formBuilder: FormBuilder,
) { }
ngOnInit() {
this.formInit();
this.getProducts();
}
formInit() {
this.form = this.formBuilder.group({
products: this.formBuilder.array([])
});
}
getProducts() {
this.productService.getProducts().subscribe(data => {
this.products.next(data);
});
}
}
<form [formGroup]="form" (ngSubmit)="formSubmit()">
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Stock</th>
<th>Stock Entrance</th>
</tr>
</thead>
<tbody formArrayName="products">
<tr *ngFor="let product of products| async">
<td>{{ product.id }}</td>
<td>{{ product.name }}</td>
<td>{{ product.stock }}</td>
<td>
<input type="number" name="stock[product.id]" >
</td>
</tr>
</tbody>
</table>
<button type="submit">Add Stock</button>
</form>
On pure html, I was able to do away with a named array, but with Angular 2 I'm trying using a reactive form, but then I should use a for loop to fill the form after a loop to generate the table for each product, this sounds like using a lot of resources to do a simple thing.
Update with methods reactive form
ProductStokeComponent.ts
ngOnInit() {
this.formInit();
this.getProducts();
}
formInit(product?: Product) {
this.form = this.formBuilder.group({
products: this.formBuilder.array([])
});
}
ProductStokeComponent.html
<tbody formArrayName="products">
Upvotes: 0
Views: 2147
Reputation: 23015
The reactive solution looks like this:
<tr *ngFor="let product of form.controls['products'].controls">
<td>{{ product.value.id }}</td>
<td>{{ product.value.name }}</td>
<td>{{ product.value.stock }}</td>
<td>
<input #moreStock>
<button (click)="addMoreStock(product.value, moreStock.value)">+</button>
</td>
</tr>
Or if you want the template forms solution:
<tbody>
<tr *ngFor="let product of products">
<td>{{ product.id }}</td>
<td>{{ product.name }}</td>
<td>{{ product.stock }}</td>
<td>
<input #moreStock>
<button (click)="addMoreStock(product, moreStock.value)">+</button>
</td>
</tr>
</tbody>
In both cases, in your TypeScript file add a method like this:
public addMoreStock(product, howMuch)
{
product.stock += parseInt(howMuch, 10);
}
Upvotes: 1