Pranav
Pranav

Reputation: 1646

Property 'update' and 'quantity' doesn't exist on type '{ }'

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>
  1. home.component.ts (the click event defined here)
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 Property quantity does not exist on type {} 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});
     }   
    });
  }

I get following error: The project compiles successfully, but key is undefined after clicking the button

This is all I have... Please see the errors again and suggest a better solution... Thanks in advance

Upvotes: 1

Views: 1339

Answers (2)

AmirHamza Sabuz
AmirHamza Sabuz

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

Sebastian Vischer
Sebastian Vischer

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

Related Questions