Passing $key of FirebaseObjectObservable into function

1k views Asked by At

I am new to Angular2 integration with Firebase so please forgive my naivety.

I'm using the AngularFire2 plugin to connect with my Firebase db and have been following their GitHub docs as such.

Up until now when I retrieve a FirebaseObjectObservable, I display it in my HTML using the async pipe described in the docs:

To get the object in realtime, create an object binding as a property of your component or service. Then in your template, you can use the async pipe to unwrap the binding.

HTML:

<ion-list *ngFor="let member of _tripMembers">
    <ion-item>
        <ion-avatar item-left>
            <img src="{{ (member | async)?.photoUrl }}">
        </ion-avatar>
        <ion-label>{{ (member | async)?.firstName }} {{ (member | async)?.lastName }}</ion-label>
        <ion-checkbox color="positive" [(ngModel)]="member.checked" (click)="toggleClicked(member, !member.checked)" item-right></ion-checkbox>
    </ion-item>
</ion-list>

When calling the toggleClicked function when the ion-checkbox is clicked, the first parameter I want to pass in is the member's key and not the full member (as is shown). This is described in the here in the docs as just using member.$key but that returns undefined.

I can display the key again by using the async pipe using:
(member | async).$key

However, I cannot do this within an arguments listings as you can't have pipes there.

EDIT:

_tripMembers is just a basic JS array that holds FirebaseObjectObservable's. Since a member is an individual item in firebase I would have thought it would be a FirebaseObjectObservable and NOT a FirebaseListObservable. The example in the documentation is that if you are getting a LIST of items, you use a FirebaseListObservable. You would use a FirebaseObjectObservable if you are only getting individual items (which is what I'm doing),

getUserWithID(userID): FirebaseObjectObservable<any> {
    return this.af.database.object('users/' + userID);
}

setTripMembers(): void {
    allUsers.forEach((user) => {
        tripMembersID.forEach((member) => {
            if (user.$key === member) {
                tripMembers.push(getUserWithID(user.$key));
            }
        });
    });


    let modal = this.modalCtrl.create(LocationModal, {
        name: name,
        members: tripMembers
    });
}

Is this wrong? Should getting an individual item be a FirebaseListObservable? If yes, can someone then please explain as in what scenario we a FirebaseObjectObservable would be used as I don't feel the docs explain it well.

Or is it that _tripMembers has to be a FirebaseListObservable<FirebaseObjectObservable>?

1

There are 1 answers

6
whatsthatitspat On

Don't use async everywhere. Just use it in the ngFor on your collection.

<ion-list *ngFor="let member of _tripMembers | async">

EDIT:

You'll want to "unwrap" the observables on the code side before they make it to your template, and without passing them around or pushing them into your array.

Take a look at this comment which helped me out when starting with AngularFire.

this.af.database.object('path') is meant to be consumed & automagically unwrapped by the template. To get the data out of it on the code side requires you to subscribe to it. But just subscribing will leave the observable in a live state. Use the take operator to get the data and close the observable.

FirebaseObjectObservable & FirebaseListObservable are simple ways to get your data showing up in a template. But once you start manipulating them you need to do more work with the Observables to create POJOs/Arrays which will end up as the model for your views.

It might end up looking something like:

let membersArray = [];

// your forEach

this.af.database.object(`path/to/${member}`)
.take(1)
.subscribe(member => {
  console.log(`member`, member);
  membersArray.push(member);
});

// end of forEach