Reputation: 1646
I'm watching the tutorial of Mosh Hamedani using the Angular version 6 but the problem is the tutorial version is 4. I'm working on the e-commerce project on AddToCart button where the product should increase it's quantity by clicking the button and updated in Firebase using productId and also if I try to add new product then id of that new product should add in AngularFire Database. I've error in the last line of item.update() and item.quantity. Please go through the code and suggest me better solution. Thanks in advance
Here is the code.
shopping-cart.service.ts
import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { Product } from '../model/product';
import { take } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ShoppingCartService {
constructor(private db: AngularFireDatabase, ) { }
private create() {
return this.db.list('/shopping-cart').push({
dateCreated: new Date().getTime()
})
}
private getCart(cartId: String) {
return this.db.object('/shopping-cart/' + cartId);
}
private getItem(cartId:string, productId: String) {
return this.db.object('/shopping-cart/' + cartId + '/items/' +productId);
}
private async getOrCreateCart() {
let cartId = localStorage.getItem('cartId');
if (cartId) return cartId;
let result = await this.create();
localStorage.setItem('cartId', result.key);
return result.key;
}
async addToCart(product: Product) {
let cartId = await this.getOrCreateCart();
let item$ = this.getItem(cartId, product.key);
item$.valueChanges().pipe(take(1)).subscribe(item => {
// I'am getting error in update() and quantity
item.update({ product: product,quantity: (item.quantity || 0) + 1});
})
}
}
Expected results are that after clicking on Add To cart button, the product quantity must be updated in firebase
Have a look at my other files(for reference) 1. home.component.html (Here is the button when clicked goes to .ts file as shown below)
<div class="card-footer">
<button (click)="addToCart(product)" style="background: #2980b9;
color:white" class="btn btn-block">Add to Cart
</button>
</div>
addToCart(product:Product) {
this.cartService.addToCart(product);
}
and the last file 3. shopping-cart.service.ts
private async getOrCreateCart() {
let cartId = localStorage.getItem('cartId');
if (cartId) return cartId;
let result = await this.create();
localStorage.setItem('cartId', result.key);
return result.key;
}
async addToCart(product: Product) {
let cartId = await this.getOrCreateCart();
let item$ = this.getItem(cartId, product.key);
item$.valueChanges().pipe(take(1)).subscribe(item => {
item$.update({ product: product,quantity: (item.quantity || 0) + 1});
})
}
Here are the error images:
1. The error is back
2. Now when I modify the above code of addToCart(product: Product) which is as:
async addToCart(product: Product) {
let cartId = await this.getOrCreateCart();
let item$ = this.getItem(cartId, product.key);
item$.snapshotChanges().pipe(take(1)).subscribe((item: any) => {
if(item.key != null) {
item$.update({ product: product,quantity: (item.quantity || 0) + 1});
} else {
item$.set( {product:product, quantity:1});
}
});
}
This is all I have... Please see the errors again and suggest a better solution... Thanks in advance
Upvotes: 1
Views: 1339
Reputation: 36
Is your products.component.ts file looking like this?
products.component.ts
import { ShoppingCartService } from './../shopping-cart.service';
import { Product } from './../models/product';
import { ActivatedRoute } from '@angular/router';
import { ProductService } from './../product.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { switchMap } from 'rxjs/operators';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: [ './products.component.css' ]
})
export class ProductsComponent implements OnInit, OnDestroy {
products: Product[] = [];
filteredProducts: Product[] = [];
category: string;
cart: any;
subscription: Subscription;
constructor(
route: ActivatedRoute,
productService: ProductService,
private shoppingCartService: ShoppingCartService
)
{
productService
.getAll()
.pipe(
switchMap((products: Product[]) => {
this.products = products;
return route.queryParamMap;
})
)
.subscribe((params) => {
this.category = params.get('category');
this.filteredProducts = this.category
? this.products.filter((p) => p.category === this.category)
: this.products;
});
}
async ngOnInit() {
this.subscription = (await this.shoppingCartService.getCart())
.valueChanges()
.subscribe((cart) => (this.cart = cart));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Here look at the ngOnInit() function. Before .subscribe() you have to write .valueChanges()
That means you have to write
async ngOnInit() {
this.subscription = (await this.shoppingCartService.getCart())
.valueChanges()
.subscribe((cart) => (this.cart = cart));
}
shopping-cart.service.ts
async addToCart(product: Product) {
let cartId = await this.getOrCreateCart();
let item$ = this.getItem(cartId, product.key);
item$.snapshotChanges().pipe(take(1)).subscribe((item) => {
if (item.payload.exists()) {
item$.update({ quantity: item.payload.exportVal().quantity + 1 });
} else {
item$.set({ product: product, quantity: 1 });
}
});
}
I think it will work. Please inform me it works or not.
Upvotes: 0
Reputation: 1310
You use the update method on the value you get from the database. You have to use the update method on a database object.
https://github.com/angular/angularfire2/blob/master/docs/rtdb/objects.md
I could not test it, let me know if it works.
async addToCart(product: Product) {
let cartId = await this.getOrCreateCart();
let itemRef = this.getItem(cartId, product.key);
itemRef.valueChanges().pipe(take(1)).subscribe(item => {
itemRef.update({ product: product,quantity: (item.quantity || 0) + 1});
})
}
Upvotes: 1