I'm getting " Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe' " when running the following code.
html template:
<ion-list>
<ion-item-sliding *ngFor="let item of shoppingItems | async">
<ion-item>
{{ item.$value }}
</ion-item>
<ion-item-options side="right">
<button ion-button color="danger" icon-only (click)="removeItem(item.$key)"><ion-icon name="trash"></ion-icon></button>
</ion-item-options>
</ion-item-sliding>
</ion-list>
page ts:
shoppingItems: AngularFireList<any>;
constructor(public navCtrl: NavController, public firebaseProvider: FirebaseProvider) {
this.shoppingItems = this.firebaseProvider.getShoppingItems();
}
firebase provider
constructor(public afd: AngularFireDatabase) {
console.log('Hello FirebaseProvider Provider');
console.log("Shopping items"+afd.list('/shoppingItems/'))
}
getShoppingItems() {
console.log("Shopping items"+this.afd.list('/shoppingItems/'))
return this.afd.list('/shoppingItems/');
}
addItem(name) {
this.afd.list('/shoppingItems/').push(name);
}
firebase db
shoppingItems
-KxmiUt64GJsPT84LQsI: "qwerty"
-KxmifqyfD41tRPwFh07: "key"
From the web app I was able to add items to firebase db. But I wasn't able to render the data from firebase. I am getting the above mentioned error.
Thanks in advance for your help.
AngularFire2 V5
this.afd.list('/shoppingItems/')
does not return an asynchronous observable which is supposed to work with async
pipe. It returns a reference to the List in the real-time database.
You need to use valueChanges()
to return that.
In your provider return the observable,
getShoppingItems() {
console.log("Shopping items"+this.afd.list('/shoppingItems/'))
return this.afd.list('/shoppingItems/').valueChanges();//here
}
If you are accessing through $key/$value
,
Check the upgrade details for angularfire2 v4 to 5. This is because FirebaseList
is deprecated and AngularFireList
is now returned from version 5.
Calling .valueChanges() returns an Observable without any metadata. If you are already persisting the key as a property then you are fine. However, if you are relying on $key, then you need to use .snapshotChanges()
You need to use snapshotChanges()
getShoppingItems() {
console.log("Shopping items"+this.afd.list('/shoppingItems/'))
return this.afd.list('/shoppingItems/').snapshotChanges();//here
}
To access $key
or $value
in html,
use item.payload.key
and item.payload.val()
Add ionViewDidLoad
life cycle in the home.ts
file and instead of constructor load your item in ionViewDidLoad
, replace your constructor with below code
constructor(public navCtrl: NavController, public firebaseProvider: FirebaseProvider) {
}
ionViewDidLoad() {
this.shoppingItems = this.firebaseProvider.getShoppingItems();
console.log(this.shoppingItems);
}
Import at page.ts
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { AngularFireDatabase} from 'angularfire2/database';
import { Observable } from "rxjs/Observable";
import { ShoppingItem } from '../../model/shoppingitem';
import your provider the right way from your provider
import { FirebaseProvider } from '../../providers/firebase/firebase';
export class Page {
shoppingItems:Observable<ShoppingItem[]>;
constructor(public navCtrl: NavController,
public firebaseProvider: FirebaseProvider) {
this.shoppingItems=this.firebaseProvider
.getShoppingItem()
.snapshotChanges()
.map(
changes=>{
return changes.map(c=>({
key:c.payload.key, ...c.payload.val(),
}));
}
);
}
}
}
firebaseProvider
note the 'shopping-list'
is the table at the firebase database
private itemListRef = this.afDatabase.list<ShoppingItem>('shopping-list');
constructor(private afDatabase: AngularFireDatabase) {}
.getShoppingItem(){
return this.itemListRef;
}
}
Your shoppingitem model
export interface ShoppingItem{
key?:string;
}