Situation: I am using FirebaseObjectObservable to populate my Ionic 2 (rc0) template. Template code:

 <p>{{(course | async)?.description}}</p>
 <button ion-button dark full large (click)="openDeckOnBrowser(course.deckUrl)">
  <ion-icon name='cloud-download'></ion-icon>
  <div>View Deck</div>
 </button>

The TS file is

  this.course = this.af.database.object('/bbwLocations/courses/' + courseId); 

this.course is a Firebase Object Observable. The problem is, this part won't work: (click)="openDeckOnBrowser(course.deckUrl). As the course.deckUrl is empty. I can not pass the value to the function.

Tho only hacky way I found to work around so far is this:

 <button id="{{(course | async)?.deckUrl}}" ion-button dark full large (click)="openDeckOnBrowser($event)">
  <ion-icon name='cloud-download'></ion-icon>
  <div id="{{(course | async)?.deckUrl}}">View Deck</div>
</button>

And on the click event:

  openDeckOnBrowser(event):void {
    console.log(event);
    let target = event.target || event.srcElement || event.currentTarget;
    let idAttr = target.attributes.id;
    let url = idAttr.nodeValue;
    console.log (url);
   }

But any official and easier way to approach this?

share|improve this question
    
Did you find any solution? I'm strugling with this. – Asaf Lopez Mar 29 at 20:39

In your template (click)="openDeckOnBrowser(course.deckUrl)" is evaluated as soon as the template is parsed. You do not use the async pipe here, hence the deckUrl is empty. You can fix this by adding a second async pipe:

<p>{{(course|async)?.description}}</p>
<button ... (click)="openDeckOnBrowser((course|async).deckUrl)">...</button>

However, this is not nice as two subscriptions will be created.

A (better) alternative:

The official docs on the AsyncPipe always use *ngFor to output a list of items and not *ngIf to output a single item. The reason is simple: the *ngIf directive does not allow any assignments. But we can work around this limitation:

The template looks as follows:

<div *ngFor="let course of course$|async">
    <p>Course: {{course?.name}}</p>
    <p>Url: {{course?.url}}</p>
</div>

And in the component, we'll just map the course to a list of a single course:

this.getCourse().map(c=>[c]);

See working Demo in Plunker

share|improve this answer
    
I just noticed that my latest changes to the Plunker were not saved yesterday. I fixed it and now it should be all correct. – Fabian Keller Oct 5 '16 at 6:40
    
I tried the solution, but it is still return empty... – Hugh Hou Oct 19 '16 at 13:46
    
The Plunker referenced in the answer works fine with the concepts presented in the answer. I would be glad to help you if you could post your non-working solution in a Plunker, as otherwise I cannot judge where the fault might be located. – Fabian Keller Oct 24 '16 at 15:10
    
I used this... and if the item isn't an iterable... you can just wrap it in a [] – Jeff Jun 6 at 20:25
1  
This is super nice! The only thing I did to make the whole thing act more like a *ngIf was to map it this way instead: .map(i => i ? [i] : undefined); On my case, this is an Observable<string> of an url used in a load more button. If the Observable gets nothing, means we should hide the button. This did the trick. – rafaelbiten Aug 17 at 14:46

Just subscribe to the observable in your code, and store the course itself in the component:

this.af.database.object('/bbwLocations/courses/' + courseId)
    .subscribe(course => this.course = course); 

Then in you view:

<p>{{ course?.description }}</p>
<button ion-button dark full large (click)="openDeckOnBrowser(course?.deckUrl)">

(although I would probably use ng-if and only show the description and the button once the course is available)

share|improve this answer
    
Well subscribe to the object defeat the whole point of Firebase Observable project. Using async pipe to optimize the code as it subscribe and unsubscribe when it is done. So it simplify lots of codes for me. With your solution, I will need to unsubscribe when the view destroy and all other cleaning jobs that aysnc pipe could dont for me. I looking for a solution that I don't even need to manually subscribe to the firebase object. – Hugh Hou Oct 4 '16 at 20:52
    
Well, good luck then... – JB Nizet Oct 4 '16 at 20:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.