Reputation: 283
I am new to Angular2...my problem is simple enough:I want to bind a array of Object like the following:
I have the following component(app.ts) and view (cart.html):
(app.ts) file:
@Component({
selector: 'my-app',
templateUrl: '../Partials/cart.html',
styleUrls: ['../Partials/cart.css']
}) export class AppComponent{
constructor(private http: Http) { };
title = 'ASP.NET MVC 5 with Angular 2';
private headers = new Headers({ 'Content-Type': 'application/json' });
invoice: Invoice = {
customer: {
CustomerName: "Lorem Ipsum",
Address: "102/102 East Hills Road",
Suburb: "East Hills",
State: "NT",
PostCode: "3563"
},
products: [
{
id: "1",
desc: "Mig Mac",
unit_price: 8.5,
quantity: 5
},
{
id: "2",
desc: "Fillet O Fish",
unit_price: 4.50,
quantity: 3
},
{
id: "3",
desc: "Icecreme",
unit_price: 0.5,
quantity: 10
}
]
}
invoice2: Invoice;
getTotal = function () {
var total = 0;
for (var i = 0; i < this.invoice.products.length; i++)
{
total += this.invoice.products[i].unit_price * this.invoice.products[i].quantity;
}
return total;
}
onSubmit() {
this.create().then(i => {
this.invoice2 = i;
console.log(this.invoice2);
});
}
create(): Promise<Invoice> {
console.log("POST");
let url = "/Invoice/Create";
return this.http.post(url, this.invoice).toPromise()
.then(res => { return res.json() as Invoice });
}
};
export class Invoice {
customer: Customer;
products: Item[];
}
export class Customer {
CustomerName: String;
Address: String;
Suburb: String;
State: String;
PostCode: String;
}
export class Item {
id: String;
desc: String;
unit_price: Number;
quantity: Number;
}
(cart.html) file:
<form #f="ngForm" (ngSubmit)="onSubmit()">
<div class="invoice-wrap">
<div class="invoice-header">
<div class="container-fluid">
<div class="row">
<div class="col-xs-6 col-xxs-12">
<div class="customer-details">
<p><strong>Invoice To</strong></p>
<input type="text" [(ngModel)]="invoice.customer.CustomerName" name="CustomerName" />
<span><strong>Address: </strong></span><br />
<input type="text" [(ngModel)]="invoice.customer.Address" name="Address" /><br />
<input type="text" [(ngModel)]="invoice.customer.Suburb" name="Suburb" /><br />
<input type="text" [(ngModel)]="invoice.customer.State" name="State" /><br />
<input type="text" [(ngModel)]="invoice.customer.PostCode" name="PostCode" /><br />
</div>
</div>
<div class="col-xs-6 col-xxs-12">
<button type="submit" [disabled]="!f.valid">Submit</button>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="item-header-wrap">
<div class="item-header hidden-xs">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2 col-xs-4">
<p>Product</p>
</div>
<div class="col-sm-3 col-xs-8">
<p>Description</p>
</div>
<div class="col-sm-2 col-xs-12">
<p>Delivery</p>
</div>
<div class="col-sm-2 col-xs-12">
<p>Click&Collect</p>
</div>
<div class="col-sm-1 col-xs-6">
<p>Unit Price</p>
</div>
<div class="col-sm-1 col-xs-6">
<p>Quantity</p>
</div>
<div class="col-sm-1 col-xs-12">
<p>Line Total</p>
</div>
</div>
</div>
</div>
</div>
<div class="item-wrap">
<div class="item" *ngFor="let product of invoice.products">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2 col-xs-4">
<div class="azure col">
<img src="./images/item.jpg" class="item-img" />
</div>
</div>
<div class="col-sm-3 col-xs-8">
<div class="orange col">
<input type="text" [(ngModel)]="product.desc" name="product.desc" value="" />
</div>
</div>
<div class="col-sm-2 col-xs-12">
<div class="azure col">
</div>
</div>
<div class="col-sm-2 col-xs-12">
<div class="click-and-collect col">
</div>
</div>
<div class="col-sm-1 col-xs-6">
<div class="red col">
<input type="text" [(ngModel)]="product.unit_price" name="product.unit_price" value="" />
</div>
</div>
<div class="col-sm-1 col-xs-6">
<div class="col">
<input type="text" [(ngModel)]="product.quantity" name="product.quantity" value="" />
</div>
</div>
<div class="col-sm-1 col-xs-12">
<div class="red col">
<p>${{product.unit_price * product.quantity}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="total">
Total = {{getTotal()}}
</div>
I get the following in the browser: where my model is populated with the last element from the object array.
Customer Part of the invoice object is binding properly but the products array of object is not binding properly. What i am doing wrong? i have searched extensively in google and tried various methods but nothing seemed to work. Please help.
Upvotes: 2
Views: 14881
Reputation: 1137
Your problem is here:
<input type="text" [(ngModel)]="product.desc" name="product.desc" value="" />
Since your HTML code is inside a form you must use a unique name per element (Input). But you probably forgot to use string interpolation, and therefore you get the following:
all elements refer to the same form attribute called simply:
product.desc
Using string interpolation in the name will fix your problem:
<input type="text" [(ngModel)]="product.desc" name="{{product.desc}}" value="" />
And you should do this everywhere you use ngModel
.
Also, as another answer suggests, you would better off adding a unique identifier to the name (such as using index with '-{{i}}') in order to avoid duplication with invoices that contain multiple items with same name.
Upvotes: 0
Reputation: 222722
You need to use ngFor
here,
<div class="item" *ngFor="let product of invoice.products;let i=index">
<input type="text" name="name-{{i}}" [(ngModel)]="product.invoice.customer.Address">
Upvotes: 0
Reputation: 3202
When creating multiple ngModel controls inside ngFor loop make sure to give each control unique name:
You can change your code like this
<div class="item" *ngFor="let product of invoice.products;let i=index">
and each input field you should change as
<input type="text" name="name-{{i}}" [(ngModel)]="your binding variable">
Hope this helps
Upvotes: 6