Category fetched as undefined from Firebse

I am saving category but getting pushed as undefined

I don’t know why



As is usually the case, we need to see the code you are using there. Can you paste the contents of the relevant .ts and .html files for that component?

sure

product-form.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { CategoryService } from 'src/app/category.service';
import { Product } from 'src/app/models/product';
import { ProductService } from 'src/app/product.service';

@Component({
  selector: 'app-product-form',
  templateUrl: './product-form.component.html',
  styleUrls: ['./product-form.component.css']
})
export class ProductFormComponent implements OnInit {
  categories$: any;

  constructor(
    private router: Router,
    private categoryService: CategoryService, 
    private productService: ProductService) { 
    this.categories$ = categoryService.getCategories();
  }   // no need to add the private access modifier as we are not going to reference this anywhere outsde the constructor

save(product: Product){  // I added HTMLInputElement from my own
  console.log(product); // I didn't get to test this because the list is not generated from firebase
  this.productService.create(product);
  this.router.navigate(['/admin/products']);
}

  ngOnInit(): void {
  }

}

product-form.component.html

<div class="row">
    <div class="col-md-6">
        <form #f="ngForm" (ngSubmit)="save(f.value)">
            <div class="form-group">
                <label for="title">Title</label>
                <input #title="ngModel" ngModel name="title" id="title" type="text" class="form-control" required>
                <div class="alert alert-danger" *ngIf="title.touched && title.invalid">Title is required</div>
            </div>
            <div class="form-group">
                <label for="price">Price</label>
                <div class="input-group-prepend">
                    <span class="input-group-text">$</span>
                    <input #price="ngModel" ngModel name="price" id="price" type="number" class="form-control" [min]="0" required>
                </div>
                <div class="alert alert-danger" *ngIf="price.touched && price.invalid">
                    <div *ngIf="price.errors.required">Price is required</div>
                    <div *ngIf="price.errors.min">Minimun Price should be 0 or higher</div>
                </div>
            </div>
            <div class="form-group">
                <label for="category">Category</label>
                <select #category="ngModel" ngModel name="category" id="category" class="form-control" required>
                    <option value=""></option>
                    <option *ngFor="let c of categories$ | async" [value]="c.$key">{{c.name}}</option>
                </select>
                <div class="alert alert-danger" *ngIf="category.touched && category.invalid">Category is required</div>
            </div>
            <div class="form-group">
                <label for="imageUrl">Image</label>
                <input #imageUrl="ngModel" ngModel name="imageUrl" id="imageUrl" type="text" class="form-control" url required>
                <div class="alert alert-danger" *ngIf="imageUrl.touched && imageUrl.invalid">
                    <div *ngIf="imageUrl.errors.required">Image Url is required</div>
                    <div *ngIf="imageUrl.errors.url">Please enter a valid URL</div>
                </div>
            </div>
            <button class="btn btn-primary">Save</button>
        </form>
    </div>
    <div class="col-md-6">
        <div class="card" style="width: 18rem;">
            <img [src]="imageUrl.value" class="card-img-top">
            <div class="card-body">
              <h5 class="card-title">{{title.value}}</h5>
              <p class="card-text">{{price.value | currency:'USD':true }}</p>
            </div>
          </div>
    </div>
</div>


Ok so I’m guessing the issue probably has to do with the stuff returned by firebase. Can you print out the category objects you are getting back from firebase so we can see what they look like? Maybe they do not have a $key field in the object.

Yes I put a photo for the category fetched.

I mean to have the values from this line printed out. You need to peek the values in the Observable and print them at the console.

I believe that would look something like this:

import { tap } from 'rxjs/operators';

...

this.categories$ = categoryService
  .getCategories()
  .pipe(tap(c => console.log("category =", c)));

Yes I copied your code, but it is only catching name not the key

Per angularfire/lists.md at master · angular/angularfire · GitHub, it looks like you may need to use snapshotChanges rather than valueChanges if you need the metadata (like keys).

1 Like

This helped me get the metadata, but not screen is empty


Thanks for your patience

I think the categories are in that payload field for the snapshots. You can inspect the object to be sure but the documentation implies you access it like this:

category.payload.val()

If you expand the object printed out you may be able to find it yourself.

image

it work for me
check category.service

image

I do in angular 15 so categories$ => categories$ : Observable<any>; and product => product:any = {};

[value]=“c.$key” => [value]=“c.key”
{{ c.name }} => {{ c.val.name }}