Reputation: 4071
I'm using a form where I have the following model repeated several times :
Bottle
I have.This pattern is repeated for 2 arrays of Bottle (the Bottle
type is made of an Id
and a Name
) as followed :
orderedBottles
where the user can order some bottles.returnedBottles
where the user can return some bottles.I want to be able to choose whatever type of bottle and corresponding count on the submit, but I believe I'm missing something because the behavior is all messed up :
Here is a working example in a plunkr : http://plnkr.co/edit/1z6dN6?p=preview
Here is my html file (I'm using AngularMaterial 2) :
<div fxLayout="row" style="max-width: 80%">
<!-- ORDERED BOTTLES -->
<div fxLayout="column" style="min-width: 50%">
<div fxLayout="row" style="max-width: 100%" *ngFor="let bottle of orderedBottles; let i = index">
<md-select class="select" placeholder="Select bottle type" name="orderedTypeSelect_{{i}}" [(ngModel)]="orderedBottles[i].typeId">
<md-option class="options" *ngFor="let type of orderedClonedArrayBottles" [value]="type.typeId">
{{ type.name }}
</md-option>
</md-select>
<md-input-container class="container">
<input md-input type="number" name="orderedBottleInput_{{i}}" autocomplete="off" [(ngModel)]="orderedBottles[i].count"
step="1" min="0" max="99">
</md-input-container>
<button class="button-row" type="button" (click)="removeRow(i, 'order')">-</button>
</div>
</div>
<!-- RETURNED BOTTLES -->
<div fxLayout="column" style="min-width: 50%">
<div fxLayout="row" style="max-width: 100%" *ngFor="let bottle of returnedBottles; let j = index">
<md-select class="select" placeholder="Select bottle type" name="returnedTypeSelect_{{j}}" [(ngModel)]="returnedBottles[j].typeId">
<md-option class="options" *ngFor="let typed of returnedClonedArrayBottles" [value]="typed.typeId">
{{ typed.name }}
</md-option>
</md-select>
<md-input-container class="container">
<input md-input type="number" name="returnedBottleInput_{{j}}" autocomplete="off" [(ngModel)]="returnedBottles[j].count"
step="1" min="0" max="99">
</md-input-container>
<button class="button-row" type="button" (click)="removeRow(j, 'return')">-</button>
</div>
</div>
</div>
To add some explanation, this is a child component that has a single Array of Bottle
as @Input()
, which I clone in 2 different arrays (orderedClonedArrayBottles
and returnedClonedArrayBottles
) so that my parent array isn't updated from the child updates.
I then display my bottles with the orderedBottles
Array and the returnedBottles
that get their values from the 2 cloned beforehand.
ngOnChanges(changes) {
// Get @Input data when it's ready
if (changes.bottleArray) {
// Cloning
//this.orderedClonedArrayBottles = [...changes.bottleArray.currentValue];
//this.returnedClonedArrayBottles = [...changes.bottleArray.currentValue];
this.orderedClonedArrayBottles = Array.from(changes.bottleArray.currentValue as Bottle[]);
this.returnedClonedArrayBottles = Array.from(changes.bottleArray.currentValue as Bottle[]);
console.log(this.orderedClonedArrayBottles);
console.log(this.returnedClonedArrayBottles);
// Display first rows
if (this.orderedClonedArrayBottles.length > 0) {
this.orderedBottles.push(this.orderedClonedArrayBottles[0]);
}
if (this.returnedClonedArrayBottles.length > 0) {
this.returnedBottles.push(this.returnedClonedArrayBottles[0]);
}
}
}
I have no idea why this isn't working correctly, most probably because I don't manage the *ngFor
as I should. I have seen posts about trackBy
for *ngFor
but I have no idea if that will help or not.
Upvotes: 0
Views: 192
Reputation: 29635
You are cloning the bottleArray
. But in your case the bottle objects are not cloned. The same references are pushed in two arrays.
Check this answer.
You may have to use Object.assign
for each bottle object.
If you have nested objects you will have to traverse the properties and copy.
Upvotes: 1