I'm using *ngFor on my mat-card so it will retrieve all the data from my book table. I also add a textbox on my card so the user can input the quantity. I used the two-way binding on my textbox. My problem is when I changed the quantity on the textbox, all the textboxes are also changed. How can I avoid this to happen? See the picture below:
Here's my code:
store.component.html
<div >
<mat-card *ngFor="let card of obs | async; let i = index" >
<img mat-card-image src="{{card.bookimage}}" width="100" height="200">
<mat-card-header>
<mat-card-title>{{card.bookname}}</mat-card-title>
<mat-card-subtitle>₱{{card.bookprice.toFixed(2)}}<span *ngIf="card.bookunitstock === 0" >Out of Stock</span></mat-card-subtitle>
</mat-card-header>
<mat-card-actions>
<input type="number" [(ngModel)]="quantity" name="quantity">
<button mat-raised-button color="primary" (click)="onAddToCartProduct(card)"><mat-icon >add_shopping_cart</mat-icon>Add to cart</button>
</mat-card-actions>
</mat-card>
</div>
store.component.ts
public onAddToCartProduct(book: Book): void {
const formValue = {
bookid: book.bookid,
bookimage: book.bookimage,
bookname: book.bookname,
bookprice: book.bookprice,
bookstatus: book.bookstatus,
cartitemid: 0,
category: "Fantasy",
checkoutstatus: true,
isbn: book.isbn,
quantity: this.quantity,
sku: book.sku,
totalprice: book.bookprice * this.quantity,
user_userid: 4
}
console.log(formValue);
this.storeService.addCartProduct(formValue).subscribe(
(response: Store) => {
this.products.push(formValue);
this.grandTotal = (formValue.quantity * formValue.bookprice);
this.successMessage("added");
},
(error: HttpErrorResponse) => {
this.errorMessage("Out -of Stock");
}
);
}
CodePudding user response:
It happens because property this.quantity
is used on all cards let card of obs
- they all reference the same prop.
Instead you could bind to prop quantity
on each individual card with [(ngModel)]="card?.quantity"
.
And on formValue
change accordingly quantity: book.quantity
.
Try to stay consistent when naming obj's, so is it a book
or a card
? Good luck!
Other option would be to use template variable. We take input
value from reference #myInput
and pass it to method onAddToCartProduct()
.
<mat-card-actions>
<input type="number" #myInput name="quantity">
<button mat-raised-button color="primary" (click)="onAddToCartProduct(card, myInput.value)"><mat-icon >add_shopping_cart</mat-icon>Add to cart</button>
</mat-card-actions>
public onAddToCartProduct(book: Book, inputValue: number): void {
const formValue = {
bookid: book.bookid,
bookimage: book.bookimage,
bookname: book.bookname,
bookprice: book.bookprice,
bookstatus: book.bookstatus,
cartitemid: 0,
category: "Fantasy",
checkoutstatus: true,
isbn: book.isbn,
quantity: inputValue, // <-----
sku: book.sku,
totalprice: book.bookprice * inputValue, // <-----
user_userid: 4
}
console.log(formValue);
this.storeService.addCartProduct(formValue).subscribe(
(response: Store) => {
this.products.push(formValue);
this.grandTotal = (formValue.quantity * formValue.bookprice);
this.successMessage("added");
},
(error: HttpErrorResponse) => {
this.errorMessage("Out -of Stock");
}
);
}