2

I have a web app that makes a request to firebase realtime database for user information.

The info is returned when the service calls the method below:

//searches db for user information
getUserInfo(uid){
    return this.db.list('users/', ref => ref.orderByKey().equalTo(uid)).valueChanges();
}

This method is triggered inside a pipe defined like so:

@Pipe({
 name: 'usernamePipe'
})

export class UsernameFilter implements PipeTransform{

constructor(private auth: AuthenticationService){
}

transform(uid: any):any {

//return item if neither filter nor list exists
if(!uid){
  return uid;
}

var user = {};

this.auth.getUserInfo(uid)
  .subscribe(res => {
    user = res;
    return user[0].userInfo.firstName;
  })
 }
}

The pipe is used on a list of messages obtained by a call to my realtime database inside my component like so:

<div class="message-summary" *ngFor="let msg of messageThread.messages | keys; let last = last" (click)="getThreadDetails(messageThread.messages)">
    <span class="time">{{msg.timeSent | date: 'short'}}</span>
    <span class="sender-name" *ngIf="msg.from !== 'admin'">{{msg.from | usernamePipe | async}}</span>
</div>

The keys pipe is another custom pipe I used to turn the objects returned from the initial request to the realtime database into an array in order to iterate over with *ngFor

Issue is that the transformed data doesn't show up in the DOM but if I try logging it to console, it shows up - proving that the method works but it's not displaying for some reason.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • one problem in your code... https://stackoverflow.com/questions/39295854/angular-2-how-to-return-data-from-subscribe – AT82 Nov 11 '17 at 07:02
  • Sorry what's the problem you speak of? – user3640687 Nov 14 '17 at 03:22
  • From what I can see, you are trying to return data from `subscribe`. – AT82 Nov 14 '17 at 04:09
  • Yes you're right about that, but trying to return from `.map` doesn't work either. I tried swapping out the `.subscribe` for `.map` and kept everything else the same but didn't get a change in the DOM either – user3640687 Nov 14 '17 at 14:26

2 Answers2

0

This happens because you are performing an asyncrhonous task and you are waiting it to be accomplished in order to change a value.

If it was inside a Component, you would see the value changed because of change detection strategy, but in this case it is inside a Pipe and pipes work differently.

From Angular documentation :

Angular looks for changes to data-bound values through a change detection process that runs after every DOM event: every keystroke, mouse move, timer tick, and server response. This could be expensive. Angular strives to lower the cost whenever possible and appropriate. Angular picks a simpler, faster change detection algorithm when you use a pipe.

So the value changes but the view isn't updated because the Change Detection isn't performed.

To perform a full change detection cycle also in case of events that happen inside a Pipe you can transform your current pipe into an impure pipe just adding a field in the metadata:

@Pipe({
 name: 'usernamePipe',
 pure: false
})
0

Simplifying the pipe to code below, getting rid of the subscribe and extras seemed to do the trick. Also the async has to be included after calling the pipe in the DOM or else nothing shows up.

return this.auth.getUserInfo(uid);

Hope someone finds this useful, feel free to message me if it doesn't work for you.