Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property 'update' does not exist on type 'Observable<{}>'. Firebase 5 AngularFire2 5

I am trying to create/update shopping-cart in firebase. I am using a service that has functions that add the localStorage ID to firebase and It add's the quantity in shopping-cart if the product already exist otherwise it created new one. The error occurred in console TypeError: Cannot read property 'quantity' of null and I also got error on compilation in shopping-cart service.ts:

  1. Property 'update' does not exist on type 'Observable<{}>'.
  2. Property 'quantity' does not exist on type '{}'

The following image demonstrate what I'm trying to get in firebase: enter image description here

shopping-cart.service.ts

import { take } from 'rxjs/operators';
import { AngularFireDatabase, snapshotChanges } from 'angularfire2/database';
import { Injectable } from '@angular/core';
import { Product } from './models/product';

@Injectable({
  providedIn: 'root'
})
export class ShoppingCartService {

  constructor(private db: AngularFireDatabase) { }

  private create(){
    console.log('shoping service')
   return this.db.list('/shopping-carts').push({
      dateCreated: new Date().getTime()
    });
  }

 private getCart(cartId: string){
   return this.db.object('/shoping-carts/'+ cartId);
 }

  private async getOrCreateCartId(){
    let cartId = localStorage.getItem('cartId');

    if(cartId) return cartId;

    let result = await this.create();
    localStorage.setItem('cartId', result.key);
    return result.key;

  }
  private getItem(cartId: string, productId: string){
    return this.db.object('/shopping-carts/' + cartId + '/items/' + productId).valueChanges();
  }

  async addToCart(product: Product){
    let cartId = await this.getOrCreateCartId();
    let item$ = this.getItem(cartId, product.key);

    item$.pipe(take(1)).subscribe( item => {
       item$.update({ product: product, quantity: (item.quantity || 0) + 1});
    });
  }

shoppng-cart.service.ts (relevant part of document)

private getItem(cartId: string, productId: string){
    return this.db.object('/shopping-carts/' + cartId + '/items/' + productId).valueChanges();
  }

  async addToCart(product: Product){
    let cartId = await this.getOrCreateCartId();
    let item$ = this.getItem(cartId, product.key);


    item$.pipe(take(1)).subscribe( item => {
       item$.update({ product: product, quantity: (item.quantity || 0) + 1});
    });
  }

product-card.component.ts

import { ShoppingCartService } from './../shopping-cart.service';
import { Product } from './../models/product';
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'product-card',
  templateUrl: './product-card.component.html',
  styleUrls: ['./product-card.component.css']
})
export class ProductCardComponent implements OnInit {

  @Input('product') product;
  @Input('show-actions') showActions = true;
  constructor(private cartService:ShoppingCartService) { }

  addToCart(product:Product){
   this.cartService.addToCart(product);
  }

  ngOnInit() {
  }

}

product-card.component.html

<div *ngIf="product.title" class="card m-auto">
    <img class="card-img-top" [src]="product.imageUrl" *ngIf="product.imageUrl" alt="{{ product.title }}">
    <div class="card-body pb-0">
      <h5 class="card-title">{{product.title}}</h5>
      <p>{{product.price | currency: 'USD'}}</p>
    </div>
    <div  class="card-footer p-0 border-top">
        <button *ngIf="showActions" (click)="addToCart(product)" class="btn btn-primary btn-block">Add to Cart</button>
    </div>
  </div>

product.ts:

export interface Product{
    key:  string;
    title: string;
    price: number;
    category: string;
    imageUrl: string;   
}
like image 816
Azhar Avatar asked Sep 24 '18 07:09

Azhar


2 Answers

After lot of searching and debugging also part of Yevgen answer I have modified my code to get rid of ERROR TypeError: Cannot read property 'quantity' of null. If I use valueChanges it makes error on new cart addition. So I changed to snapshotChanges and put some logic of it's existence and working fine now. If someone still update my answer your're most welcome.

private getItem(cartId:string, productId:string) {
  return this.db.object < any > ('/shopping-carts/' + cartId + '/items/' + productId); 
}

async addToCart(product:Product) {
  let cartId = await this.getOrCreateCartId(); 
  let item$ = this.getItem(cartId, product.key); 

  item$.snapshotChanges().pipe(take(1)).subscribe((item:any) =>  {
    if (item.key != null) {
      item$.update( {quantity:( item.payload.val().quantity || 0) + 1}); 
    }
    else{
       item$.set( {product:product, quantity:1}); 
      }
  }); 
}
like image 115
Azhar Avatar answered Nov 15 '22 01:11

Azhar


Error is pretty descriptive observable has no such property. Its because valueChanges() function returns an observable and it has only data in it. But AngularFireObject has update function and you need to use it. So you need to modify your code like:

private getItem(cartId: string, productId: string): {
  return this.db.object<any>('/shopping-carts/' + cartId + '/items/' + productId);
}

async addToCart(product: Product){
  let cartId = await this.getOrCreateCartId();
  let item$ = this.getItem(cartId, product.key);

  item$.valueChanges().pipe(take(1)).subscribe((item: any) => {
     item$.update({ product: product, quantity: (item.quantity || 0) + 1});
  });
}
like image 45
Yevgen Avatar answered Nov 15 '22 01:11

Yevgen