I have a dilemma, I’m able to delete item from database collection carts, I figured out the reason I have to reload the cart to get update on cart, this is because item is being removed from database but not from the array. I tried a number of ways to delete from array but its not working for me. I tried using splice as well as indexOf. Can someone please point me in the right direction I would greatly appreciate it. I have included a snippet of necessary code.
CartItemComponent:
cartitems$: Cartitems[] = []
cartItems: CartItem [] = []
handleRemoveFromCart(){
alert("hit remove from cartitem");
/* this.cartService.RemoveProductFromCart(this.cartItem._id).subscribe(() =>
console.log("Product with Id deleted", this.cartItem._id
//this.cartitems$ = this.cartitems$.splice(this.cartItem._id) does not work
);*/ //didn't work
this.cartService.RemoveProductFromCart(this.cartItem._id).subscribe((index =>{
console.log("Product with Id deleted", this.cartItem._id),
this.result = this.cartitems$.findIndex(p => p._id === this.cartItem._id);
if(this.result > -1){
this.cartitems$.splice(this.result, 1);
alert("Remove from array")
}
}
}
cartService:
RemoveProductFromCart(_id:string){
alert("show deleted item" + _id);
return this.http.delete<Cartitems[]>(this.rootUrl + '/getProducts/removecartitems/' + _id);
/* This goes back to calling function so I can try to delete from collection*/
}
2
Using tap
from RxJS and filter
instead of splice
handleRemoveFromCart(cartItemId: string) {
this.cartService.RemoveProductFromCart(cartItemId).pipe(
tap(() => {
this.cartItems = this.cartItems.filter(item => item._id !== cartItemId);
})
).subscribe();
}
filter
creates a new array without the specified carItemId while the tap
operator allows you to perform a “side effect”, in this case, deleting the item. Also, RemoveProductFromCart
returns void
, since there’s no need to return a new array after a delete
request.
RxJS – tap
2
The naming convention you are using for your cartitems
seems wrong, you usually use $
when the type is an Observable
, if that’s a typo from your end and it is indeed an observable, then you have to update the cartItems
by sending a new updated array like so:
component.ts
@Component({...})
export class CartComponent {
// the cart items data wrapped within an observable
cartItems$!: Observable<CartItem[]>;
//...
// first approach:
onDeleteItem(id: string): void {
this.cartService.RemoveProductFromCart(id)
.pipe(
take(1),
withLatestFrom(this.cartItems$) // grab the current data in the cart items
)
.subscribe(([response, cartItems]: [ResponseService, CartItem[]]) => {
const filtered = cartItems.filter(e => e._id !== id); // remove the deleted item
this.cartItems$.next(filtered); // update the cart items
})
}
// second approach: (There are many actually...)
onDeleteItem2(id: string): void {
this.cartItems$ = this.cartService.RemoveProductFromCart(id)
.pipe(
withLatestFrom(this.cartItems$),
concatMap(([response, cartItems]: [ResponseService, CartItem[]]) => {
const filtered = cartItems.filter(e => e._id !== id)
return of(filtered);
})
)
}
}
component.html
<!-- This is just an example on how to handle your cart items source -->
<!-- within the template HTML -->
<ng-container *ngIf="cartItems$ | async as items">
<li *ngFor="let item of items">{{ item.name }} - {{ item.price }}</li>
</ng-container>
<!-- If you are using the latest version of Angular, you could do it like this -->
@if (cartItems$ | async; as items) {
@for (item of items; track item) {
<li>{{ item.name }} - {{ item.price }}</li>
}
}
In the first approach, it subscribes manually to the http response from the server and in it, you next
it with the updated cart items.
The second one, you don’t subscribe
, instead you pipe
it and return a final Observable
holding the updated cart items.
Additionally, you should also handle the possible scenario of an error with catchError
, but I didn’t implemented since I am not sure if you are already doing that in your project.
As a side note, I am not sure why you have 2 cartItems
declared in your component, both seems to be of the same type, the only differences are the names, one doesn’t have $
the other one does it which is very confusing.
Maybe try the following:
handleRemoveFromCart(cartItem: CartItem) {
this.cartService.removeProductFromCart(cartItem._id).subscribe(
() => {
console.log("Product with Id deleted", cartItem._id);
const index = this.cartItems.findIndex(item => item._id === cartItem._id);
if (index > -1) {
this.cartItems.splice(index, 1);
console.log("Item removed from local array");
}
},
(error) => {
console.error('Error removing item from cart:', error);
}
);}