Livi17
Livi17

Reputation: 1660

Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'

I'm trying to follow this youtube video tutorial and at the 8:22 point of the video, I am running into the following error:

Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'

enter image description here

This his how the information is stored in firebase. enter image description here

The data is set in firebase by a profile.html page.

<ion-content padding>
    <ion-item>
        <ion-label floating>Username</ion-label>
        <ion-input [(ngModel)]="profile.username"></ion-input>
    </ion-item>
    <ion-item>
        <ion-label floating>First Name</ion-label>
        <ion-input [(ngModel)]="profile.firstname"></ion-input>
    </ion-item>
    <ion-item>
        <ion-label floating>Last Name</ion-label>
        <ion-input [(ngModel)]="profile.lastname"></ion-input>
    </ion-item>

    <button ion-button block (click)="createProfile()">Create Profile</button>

</ion-content>

this profile.ts looks like this

import { Profile } from '../../models/profile';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase } from 'angularfire2/database';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';

/**
 * Generated class for the ProfilePage page.
 *
 * See https://ionicframework.com/docs/components/#navigation for more info on
 * Ionic pages and navigation.
 */

@IonicPage()
@Component({
  selector: 'page-profile',
  templateUrl: 'profile.html',
})
export class ProfilePage {

    profile = {} as Profile;

  constructor(
    private afAuth: AngularFireAuth,
    private afDatabase: AngularFireDatabase,
    public navCtrl: NavController, 
    public navParams: NavParams) {
  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad ProfilePage');
  }

  createProfile(){
    this.afAuth.authState.take(1).subscribe(auth => {
        this.afDatabase.object(`profile/${auth.uid}`).set(this.profile)
        .then(() => this.navCtrl.setRoot('HomePage'));
    })
  }

}

The models/profile.ts looks like:

export interface Profile {
    username: string;
    firstName: string;
    lastName: string;
}

At this point in the tutorial we are just simply trying to display the username on the homepage.

My home.ts file looks like this:

import { Item } from './../../models/item/item.model';
import { Profile } from './../../models/profile';
import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';
import { Component } from '@angular/core';
import { NavController, IonicPage, ToastController } from 'ionic-angular';
import { ShoppingListService } from '../../services/shopping-list/shopping-list.service';
import { Observable } from 'rxjs/Observable';
import { AngularFireAuth } from 'angularfire2/auth';

@IonicPage()

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  profileData: FirebaseObjectObservable<Profile>
    shoppingList$: Observable<Item[]>

  constructor(
    private afAuth: AngularFireAuth,
    private afDatabase: AngularFireDatabase,
    private toast: ToastController,
    public navCtrl: NavController,
    private shopping:ShoppingListService) {
    this.shoppingList$ = this.shopping
        .getShoppingList()
        .snapshotChanges()
        .map(
            changes => {
                return changes.map(c => ({
                    key: c.payload.key, ...c.payload.val()
                }));
            });
  }

  ionViewWillLoad(){
      this.afAuth.authState.subscribe(data => {
        if(data && data.email && data.uid){
          this.toast.create({
            message: `Welcome to the Jungle, ${data.email}`,
            duration: 3000
          }).present();
          this.profileData = this.afDatabase.object(`profile/${data.uid}`)

        } else {
        this.toast.create({
            message: `Could not log you in`,
            duration: 3000
          }).present();
      }
    }
  )}

My home.html page looks like this:

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Shopping List
    </ion-title>
    <ion-buttons end>
        <button navPush='AddShoppingItemPage' ion-button>
            <ion-icon name="add"></ion-icon>
        </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <p>Username: {{(profileData | async)?.username}}</p>
  <ion-list>
    <ion-list-header>
      Items
    </ion-list-header>
    <ion-item *ngFor="let item of shoppingList$ | async" detail-push navPush="EditShoppingItemPage" [navParams]="{item: item}">
      {{item.name}}
    </ion-item>
  </ion-list>
</ion-content>

It seems as though either this line in home.ts:

this.profileData = this.afDatabase.object(`profile/${data.uid}`)

or this line:

profileData: AngularFireObject<Profile>

or this line:

import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';

is the culprit.

However, I'm not sure how to fix it. I have followed the tutorial exactly as the author has instructed, and it works fine for him. The tutorial is only 5 months old. I know that the technology is changing rapidly and 5 months is a long time, but its advancing so quickly that it makes learning it impossible as all the tutorials are broken immediately after they are published. You spend more time fixing errors that as a beginner you don't understand and can't comprehend.

Upvotes: 2

Views: 8298

Answers (3)

fitch
fitch

Reputation: 1104

Hey

When working with the real-time database, version 5 is not using FirebaseListObservable and FirebaseObjectObservable anymore, instead, now it uses AngularFireList for lists and AngularFireObject for objects.

You should use valueChanges() now. If you add .valueChanges() afterwards, directly in the same statement, you are basically getting the Observable (whether it is a list or an object) of that AngularFireObject/List to which you can subscribe then.

So what you need to do should be looking like this :

this.profileData = this.afDatabase.object(`profile/${data.uid}`).valueChanges()

profileData should now be declared as an Observable like this (import { Observable } from 'rxjs';)

profileData : Observable<any>

and now in your view you should be able to see your property like so

{{ (profileData | async)?.firstname }}

Upvotes: 0

Ivan Simic
Ivan Simic

Reputation: 41

This worked for me {{ (profileData)?.username}}

Upvotes: 1

cgatian
cgatian

Reputation: 22994

The profileData property is not an observable so you can't use the async pipe with it.

Update your template with the following:

  <p>Username: {{profileData?.username}}</p>

Upvotes: 2

Related Questions