Search code examples
angularfireangularfire5

Returning $key in AngularFire 5


I have the following code that works with AngularFire 5:

export class NavigationComponent {
    items: Observable<any[]>;
    constructor(db: AngularFireDatabase) {
        this.items = db.list('/pages', ref => {
            let query = ref.limitToLast(100).orderByChild('sortOrder');
            return query;
        }).valueChanges();
    }
}

But now need to return item.$key which apparently is no longer returned by default in AngularFire 5. I see mention in the migration guide of needing to "map" this, but can't seem to get the right syntax working on the above code.


Update: followed the advice below, and it seemed to have worked but there appears to be some difference still between the behavior between old and new.

<nav class="nav-standard">
    <app-logo></app-logo>
    <div class="nav-dropdown">
        <ul *ngFor="let item of items | async | filter : 'parent' : '00000000-0000-0000-0000-000000000000'" class="nav-dropdown">
            <li>
                <a mat-button class="mat-button" href="{{item.path}}" data-id="{{item.key}}" target="{{item.target}}" title="{{item.tooltip}}"  [attr.data-sort]="item.sortOrder" *ngIf="item.content; else elseBlock">{{item.menuText}}</a>
                <ng-template #elseBlock>
                    <a mat-button class="mat-button" data-id="{{item.key}}" target="{{item.target}}" title="{{item.tooltip}}">{{item.menuText}}</a>
                </ng-template>
                <ul class="nav-dropdown-content">
                    <li *ngFor="let childItem of items | async | filter : 'parent' : item.key" class="">
                        <a class="mat-button" href="{{childItem.path}}" data-id="{{childItem.key}}" target="{{childItem.target}}" title="{{childItem.tooltip}}" [attr.data-sort]="childItem.sortOrder">{{childItem.menuText}}</a>
                    </li>
                </ul>
            </li>
        </ul>   
    </div>
</nav>

The nested *ngFor never seems to fire, whereas before it did. It appears that items in the nested *ngFor is null ?? I found if I create another Observable in my component called childItems and assign duplicate logic to that, it works okay -- but to me that feels dirty and wrong. How can I get the data in the observable to persist long enough to use it in the nested *ngFor ?


Solution

  • item key information isn't 'free' anymore upon the new AngularFire API changes. Instead of use '.valueChanges()' to turn reference into Observable, you can use '.snapshotChanges()':

        .snapshotChanges()
        .map(changes => {
          return changes.map(change => ({key: change.payload.key, ...change.payload.val()}));
        })
    

    from then on you can reference item key by using 'item.key' (notice that you cannot use '$key').