Search code examples
angularfirebase-realtime-databaseangularfire2

How to get lists items in firebase database


I have following database structure

enter image description here

What l am try to do is getting menulist nested of Categories main list . I have no problem on getting Categories but I have tried getting the list of menulist . I have empty page .

Code

  ngOnInit() {
    this.categories = this.af.list("Categories")

    this.categories.snapshotChanges()
    .pipe(
      map(changes =>
        changes.map(c => ({ $key: c.payload.key, ...c.payload.val() }))
      )
    ).subscribe((data: any) => {
      this.categories = data

      console.log(this.categories);
    })

  }

HTML

<tbody  *ngFor="let item of categories.menulist">
<tr role="row" class="even text-right">
<td class="text-right">{{item.body}}</td>
<td class="text-center">{{item.title}}</td>  
</tr>
</tbody>

any idea how to get menu list nested of Categories main list ?


Solution

  • Your menulist is an object, but you need it to be an array.

    One solution is to make it an array in TypeScript. For example:

    subscribe((data: any) => {
        this.categories = data.map(category => {
            const menuKeys = Object.keys(category.menulist || {});
            const menulist = menuKeys.map(menuKey => category.menulist[menuKey]);
            return { ...category, menulist };
        });
        console.log(this.categories);
    });
    

    Then you need to loop through the categories AND through their menulist items:

    <tbody>
      <ng-container *ngFor="let category of categories">
        <tr *ngFor="let item of category.menulist" role="row" class="even text-right">
          <td class="text-right">{{item.body}}</td>
          <td class="text-center">{{item.title}}</td>  
        </tr>
      </ng-container>
    </tbody>
    

    Another solution is to use a keyvalue pipe, like this:

    <tbody>
      <ng-container *ngFor="let category of categories">
        <tr *ngFor="let item of category.menulist | keyvalue" role="row"
                                                    class="even text-right">
          <td class="text-right">{{item.value.body}}</td>
          <td class="text-center">{{item.value.title}}</td>  
        </tr>
      </ng-container>
    </tbody>
    

    I didn't test these, so watch out for typos.

    Also don't forget to unsubscribe in ngOnDestroy.


    You also asked how to delete a specific item from some category's menulist.

    To do this, you need to know the menulist item's key. Replace

    const menulist = menuKeys.map(menuKey => category.menulist[menuKey]);
    

    with

    const menulist = menuKeys.map(key => ({...category.menulist[key], key}));
    

    and then you can do

    this.af.object(`Categories/${category.$key}/menulist/${item.key}`).remove();