Moblize IT
Moblize IT

Reputation: 1278

Angular and Ionic 4 to listen to live data Error: InvalidPipeArgument: '' for pipe 'AsyncPipe'

I am trying to update messages in my ionic 4 app in realtime using angularfire2 and firebase realtime database. The code looks like below

On running it throws the exception Error: InvalidPipeArgument: '' for pipe 'AsyncPipe'

if i remove the word async then it shows up fine but when i post a new message from another instance then the entire data repeats.

html

<ion-list lines="full" style="background:transparent">
                    <ion-item  style="padding-top:10px;" *ngFor="let msg of messages | async">
                        <ion-row  style="width:100%;">
                            <ion-col size="3">
                                <ion-row>
                                    <ion-col class="sg-reg-text">{{formatName(msg.name)}}</ion-col>
                                </ion-row>
                                <ion-row>
                                    <ion-col style="padding:0;padding-left:8px" class="sg-tiny-text"><ion-icon name="time" color="light"></ion-icon>&nbsp;now</ion-col>
                                </ion-row>
                            </ion-col>
                            <ion-col style="border-bottom: 1px solid #7e7c8d;padding-bottom: 10px">
                                <ion-row>
                                    <ion-col class="sg-reg-text">{{msg.message}}</ion-col>
                                </ion-row>
                            </ion-col>
                        </ion-row>
                    </ion-item>
              </ion-list>

ts

messages:Post[]
refresh(){
this.messages = []
this.sgSvc.getMessages().subscribe(
  (rsp:any) => {
                  for(let data of rsp){
                    console.log("hehe:" + JSON.stringify(data))
                    this.messages.push(new Post(data._name, data._message, data._uid))
                  }

                }
)
  }

ngOnInit() {
this.refresh()
}

svc.ts

private msgList: AngularFireList<Post>

getMessages(){

this.msgList = this.db.list<Post>('posts')
return this.msgList.snapshotChanges().pipe(
   map(changes => 
    changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
   )
  );
  }

Upvotes: 1

Views: 342

Answers (1)

Alexander Staroselsky
Alexander Staroselsky

Reputation: 38847

Try the following using the RxJS map() operator to build the array of Post objects rather than pushing the items to messages each time in subscribe(). You receive duplicate data when you remove the async pipe with your current code because you are not re-initializing the array to an empty array. Either way you wouldn't use the async pipe with an Array<T>:

messages: Observable<Post[]>;

// ...

this.messages = this.sgSvc.getMessages().pipe(
  map((messages: any) => messages.map(m => new Post(m._name, m._message, m._uid)));
);

You can also approach it without the async pipe:

messages: Post[] = [];

// ...

this.sgSvc.getMessages().subscribe((messages: any) => {
  this.messages = messages.map(m => new Post(m._name, m._message, m._uid));
});

Hopefully that helps!

Upvotes: 1

Related Questions