brians69
brians69

Reputation: 485

User information not being displayed

I have a case where I display some user information using a pipe:

{{ author.id | user: 'name' }}

I get the id from an author and, then, I use the user pipe to get its information stored in /users/$uid. Here's my pipe:

export class UserPipe implements PipeTransform {
  constructor(private af: AngularFire) {}

  transform(uid: string, field: any): any {
    let data = {};

    let fb = this.af.database.object(`/users/${uid}`);
    fb.subscribe(res => {
      data = res;
      console.log(data[field]);
    });

    return data[field];
  }
}

This is working fine if the author is the current logged in user. However, the name isn't being displayed for others.

The name is printed normally in the console, however it's still not showing up in the HTML. I also double checked Firebase's security rules and it's fine. I don't get any errors in the console.

Upvotes: 0

Views: 56

Answers (1)

yuxhuang
yuxhuang

Reputation: 5389

Your transform() function has used an observable. The simpliest approach is wrapping your result with an AsyncPipe if you want to consolidate the mapping logic into the pipe.

@Pipe({
  name: 'user',
  pure: false
})
export class UserPipe implements PipeTransform {
  private asyncPipe: AsyncPipe;

  constructor(ref: ChangeDetectorRef, private af: AngularFire) {
    this.asyncPipe = new AsyncPipe(ref);
  }

  transform(uid: string, field: any): any {
    let fb = this.af.database.object(`/users/${uid}`).map(res => res[field]);
    return this.asyncPipe.tranform(fb);
  }
}

Or if you would like to implement this feature in a component, though not recommended, just for fun

@Component({
  selector: 'my-user',
  template: '{{ result | async }}'
})
export class UserComponent {
  @Input() uid: string;
  @Input() field: string;
  result: Observable<any>;

  constructor(private af: AngularFire) {}

  ngOnChanges(changes: SimpleChanges) {
    let field = changes.field.currentValue;
    let uid = changes.uid.currentValue;
    if (uid && field) {
      this.result = this.af.database.object(`/users/${uid}`).map(res => res[field]);
    }
    else {
      this.result = Observable.of(null);
    }
  }
}

Use this with:

<my-user uid="12345" field="name"></my-user>

Or alternatively, you can just do what is suggested in the comment, just return this.af.database.object('/users/uid') and pipe the result with async pipe.

Upvotes: 2

Related Questions