2

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.

Livi17
  • 1,620
  • 3
  • 25
  • 43
  • How does the actual data look like that you are receiving? – AT82 Dec 10 '17 at 09:23
  • On the home page it's not displaying any data from firebase. See the screenshot above. I have since removed the pipe and async from the home.html page following cgatian's advice below, and it will display the home page, but it does not receive any data from firebase. – Livi17 Dec 10 '17 at 16:13
  • Yeah, I understand it's not showing, that is why I asked for how the data looks like ;) i.e, copy paste the JSON you are receiving. – AT82 Dec 10 '17 at 17:52
  • Sorry, I misunderstood your question. I will edit the question above to show that. – Livi17 Dec 11 '17 at 23:07
  • Seemingly the problem is with the async pipe, i.e related to your shopping list. But also the profile seems to be the problem. You are getting an object with the properties you want (firstname, lastname, username) nested so you need to check that you have the correct property path to your properties, since when you look at it, there is for example no property path like `profileData.username`, username is nested inside the key `ovwO......` – AT82 Dec 12 '17 at 04:24

3 Answers3

2

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>
cgatian
  • 22,047
  • 9
  • 56
  • 76
  • That makes the error go away, but it does not accomplish the intended goal of making the username appear on the homepage where it should. Nothing appears. Is profileData property supposed to be an observable? – Livi17 Dec 09 '17 at 15:40
1

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

Ivan Simic
  • 41
  • 2
  • 9
0

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 }}
Fitch
  • 1,084
  • 1
  • 11
  • 17