Search code examples
angulartypescriptfirebaseangularfire

Problem in getting list of products from firebase in Angular 16


I'm trying to display the list of products in a tabular format. Although I am getting table headings but I am unable to retrieve data from the firebase.

admin-products.component.html

<p>
    <a routerLink="/admin/products/new" class="btn btn-primary"> New Product</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>Title</th>
            <th>Price</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let p of products$| async">
            <td>{{ p.payload.val().title }}</td>
            <td>{{ p.payload.val().price }}</td>
            <td>
                <a [routerLink]="['/admin/products/', p.key]">Edit</a>
            </td>
        </tr>
    </tbody>
</table>

product.service.ts

import { Injectable } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/compat/database';

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

  constructor(private db: AngularFireDatabase) { }

  create(product) {
    this.db.list('/products ').push(product); 
  }

  getAll() {
    return this.db.list('/product').snapshotChanges(); 
  }
}

admin-product.component.ts

import { Component } from '@angular/core';
import { ProductService } from 'src/app/product.service';

@Component({
  selector: 'app-admin-products',
  templateUrl: './admin-products.component.html',
  styleUrls: ['./admin-products.component.css']
})
export class AdminProductsComponent {
  products$:any;

  constructor(private productService: ProductService){
    this.products$ = this.productService.getAll();
  }

}

exported database json flle

{
  "categories": {
    "action": {
      "name": "Action"
    },
    "adventure": {
      "name": "Adventure"
    },
    "fighting": {
      "name": "Fighting"
    },
    "puzzle": {
      "name": "Puzzle"
    },
    "strategy": {
      "name": "Strategy"
    }
  },
  "products ": {
    "-NdjCd4DNpztAOwiR1Hk": {
      "category": "Action",
      "imageUrl": "https://cdn.cloudflare.steamstatic.com/steam/apps/1888160/ss_549f55589c10866bc31243d277324e31ad155b29.600x338.jpg?t=1694077391",
      "price": 3599,
      "title": "ARMORED CORE™ VI FIRES OF RUBICON™"
    },
    "-Ndu1DegkAnM2FWqx1tu": {
      "category": "Action",
      "description": "In space, no one can hear you scream … except your friends! Rally your crew, man your spaceship, and prepare for an epic adventure. Battle fearsome foes, salvage valuable loot, die repeatedly - while reclaiming humanity's lost territory together.",
      "imageUrl": "https://cdn.cloudflare.steamstatic.com/steam/apps/1063420/header.jpg?t=1694177016",
      "price": 2999,
      "title": "Void Crew"
    }

Pic for the webpage. (https://i.sstatic.net/eiYtE.png)


Solution

  • You don't seem to have a product key in the database, instead only a products key. Therefore change the getAll() method to the following:

      getAll() {
        return this.db.list('/products ').snapshotChanges();
        .pipe(map( action => action
          .map(a => {
            const key = a.payload.key;
            const data = a.payload.val();
            return  data;
          }))); 
      }
    

    Then in the template do the following:

     <tbody>
            <tr *ngFor="let p of products$| async">
                <td>{{ p.title }}</td>
                <td>{{ p.price }}</td>
                <td>
                    <a [routerLink]="['/admin/products/', p.key]">Edit</a>
                </td>
            </tr>
        </tbody>