GeorgeMenezes
GeorgeMenezes

Reputation: 93

ERROR Error: Reference.set failed: First argument contains an invalid key ($key) in property

im a newbie to angular and I'm trying to implement add-to-cart functionality on an angular project. here is the function that adds to cart:

  async addToCart(product: Productsobj) {
    let cartId = await this.getOrCreateCartId();
    let item$ = this.db.object(
      "/shopping-carts/" + cartId + "/items/" + product.$key
    );
    item$
      .valueChanges()
      .pipe(take(1))
      .subscribe((p: any) => {
        if (p) item$.update({ quantity: p.quantity + 1 });
        else item$.set({ product: product, quantity: 1 });
      });
  }

here is the error :

core.js:6014 ERROR Error: Reference.set failed: First argument contains an invalid key ($key) in property 'shopping-carts.-Lw2GnUrgt9nMyNKznlW.items.-KrqgOLs07ZkbapP4EGi.product'. Keys must be non-empty strings and can't contain ".", "#", "$", "/", "[", or "]"

i tried changing the function as :

  async addToCart(product: Productsobj) {
    let cartId = await this.getOrCreateCartId();
    let item$ = this.db.object(
      "/shopping-carts/" + cartId + "/items/{{product.$key}}"// changed product.$key
    );
    item$
      .valueChanges()
      .pipe(take(1))
      .subscribe((p: any) => {
        if (p) item$.update({ quantity: p.quantity + 1 });
        else item$.set({ product: product, quantity: 1 });
      });
   }

now getting the error as :

core.js:6014 ERROR Error: Uncaught (in promise): Error: Reference.child failed: First argument was an invalid path = "/shopping-carts/-Lw2GnUrgt9nMyNKznlW/items/{{product.$key}}". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"

how do i unwrap the product.$key properly?

edit: the product argument is an object : console.log(product) product

after changing product:product to productName:product.title errors are gone , firebase shows: firebase

is there a way to get the whole object in firebase?

Upvotes: 2

Views: 1919

Answers (4)

Muhammad Shahab
Muhammad Shahab

Reputation: 411

I have solved the problem.

Before (With Error)

  async addToCart(product: Product) {
    let cartId = await this.getOrCreateCartId();
    let item$ = this.getItem(cartId, product.$key as string);
    item$
      .valueChanges()
      .pipe(take(1))
      .subscribe((item: any) => {
        if (item == null)
          item$.set({
            product: product,
            quantity: 1,
          });
        else item$.update({ quantity: item.quantity + 1 });
      });
  }

After (Without Error)

  async addToCart(product: Product) {
    let cartId = await this.getOrCreateCartId();
    let item$ = this.getItem(cartId, product.$key as string);
    item$
      .valueChanges()
      .pipe(take(1))
      .subscribe((item: any) => {
        if (item == null)
          item$.set({
            product: {
              title: product.title,
              category: product.category,
              price: product.price,
              imageUrl: product.imageUrl,
            },
            quantity: 1,
          });
        else item$.update({ quantity: item.quantity + 1 });
      });
  }

just change the Implicit product object to Explicit product object

Upvotes: 0

Sumir  Mathur
Sumir Mathur

Reputation: 19

Use the following for the definition of Productsobj interface:

export interface Productsobj
{
   key: string; 
   title: string; 
   price: number; 
   category: string; 
   imageUrl: string;
}

i.e instead of using "$key" use "key". With this the following code works

async addToCart(product: Productsobj) {
   const cartId = await this.addOrGetCartId();
   const item$ = this.db.object('/shopping-carts/' + cartId + '/items/' + product.key);
   item$.valueChanges().pipe(take(1)).subscribe( (item:any) => {
      if (item) item$.update({quantity: item.quantity + 1});
      else item$.update({product: product, quantity: 1});
 });
}

Firebase does not allow you to have keys starting with $ character. If you try to add a new object in database (using firebase console) with key as "$key", following error is flagged: 'Path contains invalid characters'. This is why you are getting error in your Angular app.

Upvotes: 0

srinivas-kotagiri
srinivas-kotagiri

Reputation: 11

Use product.payload.val() to set the product attribute to the product object as follows:

async addToCart(product){
  let cartId= await this.getOrCreateCartId();
  let item$=  this.db.object('/shopping-carts/' + cartId + '/items/' + product.key);
  item$.valueChanges().pipe(take(1)).subscribe((item:any) => {
    if(item!=null) {
      item$.set({product: product.payload.val(), quantity: item.quantity + 1})
    }
    else item$.set({product: product.payload.val(), quantity: 1});
  });
}


Upvotes: 1

Peter Haddad
Peter Haddad

Reputation: 80914

Try the following:

let key = product["$key"];
let item$ = this.db.object("/shopping-carts/" + cartId + "/items/" + key);

Use brackets to access the property $key. Also it's better if you change the property $key to just key

Upvotes: 1

Related Questions