P_Js
P_Js

Reputation: 623

Angular 4: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'

i need your help, i'm trying to display some datas from my firebase but it trhows me an error like InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'.


There is my service:

import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';

@Injectable()
export class MoviesService {

  constructor(private db: AngularFireDatabase) {}
  get = () => this.db.list('/movies');
}

There is my component:

import { Component, OnInit } from '@angular/core';
import { MoviesService } from './movies.service';

@Component({
  selector: 'app-movies',
  templateUrl: './movies.component.html',
  styleUrls: ['./movies.component.css']
})
export class MoviesComponent implements OnInit {
  movies: any[];

  constructor(private moviesDb: MoviesService) { }

  ngOnInit() {
    this.moviesDb.get().subscribe((snaps) => {
      snaps.forEach((snap) => {
        this.movies = snap;
        console.log(this.movies);
      });
   });
 }
}

And there is mmy pug:

ul
  li(*ngFor='let movie of (movies | async)')
    | {{ movie.title | async }}

Upvotes: 61

Views: 179474

Answers (7)

Simon_Weaver
Simon_Weaver

Reputation: 145880

Observables > Signals

If you have been converting code from using Observable to signal you may come across the following variation of the error:

Error: NG02100: InvalidPipeArgument: 'function () { [native code] }' for pipe 'AsyncPipe'

The 'native code' part looks a little scary at first but it is simply the string representation of a signal with its unique Symbol.

Simple click on the first line of code in the error message that looks like yours, to find where in the template you switched to using a signal but didn't update the async pipe.

enter image description here

So before you may have had:

favoriteColor: Observable<string>;

{{ favoriteColor | async }}

Now as a signal it should be:

favoriteColor: Signal<string>;

{{ favoriteColor() }}

Upvotes: 0

JGFMK
JGFMK

Reputation: 8904

You get this message when you've used async in your template, but are referring to an object that isn't an Observable.

So for examples sake, let's say I had these properties in my class:

job:Job
job$:Observable<Job>

Then in my template, I refer to it this way:

{{job | async }}

instead of:

{{job$ | async }}

You wouldn't need the job:Job property if you use the async pipe, but it serves to illustrate a cause of the error.

Upvotes: 23

smit agravat
smit agravat

Reputation: 295

Ok I had a similar problem now I solved it so let me explain what you can do but first I don't know which version of angular you are using so the method can be different I am adding my setup version below

Angular CLI: 13.3.1
Node: 16.14.2
Package Manager: npm 8.5.0
OS: win32 x64

Angular: 13.3.1
... animations, cli, common, compiler, compiler-cli, core, forms    
... platform-browser, platform-browser-dynamic, router

Package                         Version

    @angular-devkit/architect       0.1303.1
@angular-devkit/build-angular   13.3.1
@angular-devkit/core            13.3.1
@angular-devkit/schematics      13.3.1
@angular/fire                   7.3.0
@schematics/angular             13.3.1
rxjs                            7.5.5
typescript                      4.6.3

1 First change is your service file, change it from

import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';

    @Injectable()
    export class MoviesService {

      constructor(private db: AngularFireDatabase) {}
      get = () => this.db.list('/movies');
    }

To this,

    import { Injectable } from '@angular/core';
    import { AngularFireDatabase } from 'angularfire2/database';

    @Injectable()
    export class MoviesService {

      constructor(private db: AngularFireDatabase) {}
      get(): Observable<any[]>{
          return this.db.list('/movies')
      } 
    }

Note:- Don't forget to import Observable from proper module

Then change your component from this

import { Component, OnInit } from '@angular/core';
import { MoviesService } from './movies.service';

    @Component({
      selector: 'app-movies',
      templateUrl: './movies.component.html',
      styleUrls: ['./movies.component.css']
    })
    export class MoviesComponent implements OnInit {
      movies: any[];

      constructor(private moviesDb: MoviesService) { }

      ngOnInit() {
        this.moviesDb.get().subscribe((snaps) => {
          snaps.forEach((snap) => {
            this.movies = snap;
            console.log(this.movies);
          });
       });
     }
    }

To something like this

import { Component, OnInit } from '@angular/core';
import { MoviesService } from './movies.service';

    @Component({
      selector: 'app-movies',
      templateUrl: './movies.component.html',
      styleUrls: ['./movies.component.css']
    })
    export class MoviesComponent implements OnInit {
      movies$: any;

      constructor(private moviesDb: MoviesService) { }

      ngOnInit() {
        this.movies$ = this.moviesDb.get()
        .subscribe((snaps) => {
          snaps.forEach((snap) => {
            this.movies$ = snap;
            console.log(this.movies$);
          });
       });
     }
    }

And your last file from this

ul
   li(*ngFor='let movie of (movies | async)')
      | {{ movie.title | async }}

To this

ul
    li(*ngFor='let movie of (movies | async)')
        | {{ movie.title }}

I am not a pro but I solved it this way and hope it works for you too

Upvotes: 0

Nizam Uddin
Nizam Uddin

Reputation: 318

In your MoviesService you should import FirebaseListObservable in order to define return type FirebaseListObservable<any[]>

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

then get() method should like this-

get (): FirebaseListObservable<any[]>{
        return this.db.list('/movies');
    }

this get() method will return FirebaseListObervable of movies list

In your MoviesComponent should look like this

export class MoviesComponent implements OnInit {
  movies: any[];

  constructor(private moviesDb: MoviesService) { }

  ngOnInit() {
    this.moviesDb.get().subscribe((snaps) => {
       this.movies = snaps;
   });
 }
}

Then you can easily iterate through movies without async pipe as movies[] data is not observable type, your html should be this

ul
  li(*ngFor='let movie of movies')
    {{ movie.title }}

if you declear movies as a

movies: FirebaseListObservable<any[]>;

then you should simply call

movies: FirebaseListObservable<any[]>;
ngOnInit() {
    this.movies = this.moviesDb.get();
}

and your html should be this

ul
  li(*ngFor='let movie of movies | async')
    {{ movie.title }}

Upvotes: 19

Sanjeet kumar
Sanjeet kumar

Reputation: 3441

I found another solution to get the data. according to the documentation Please check documentation link

In service file add following.

import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';

@Injectable()
export class MoviesService {

  constructor(private db: AngularFireDatabase) {}
  getMovies() {
    this.db.list('/movies').valueChanges();
  }
}

In Component add following.

import { Component, OnInit } from '@angular/core';
import { MoviesService } from './movies.service';

@Component({
  selector: 'app-movies',
  templateUrl: './movies.component.html',
  styleUrls: ['./movies.component.css']
})
export class MoviesComponent implements OnInit {
  movies$;

  constructor(private moviesDb: MoviesService) { 
   this.movies$ = moviesDb.getMovies();
 }

In your html file add following.

<li  *ngFor="let m of movies$ | async">{{ m.name }} </li>

Upvotes: 8

Aravind
Aravind

Reputation: 41533

You should add the pipe to the interpolation and not to the ngFor

ul
  li(*ngFor='let movie of (movies)') ///////////removed here///////////////////
    | {{ movie.title | async }}

Reference docs

Upvotes: 0

Adnan A.
Adnan A.

Reputation: 1982

async is used for binding to Observables and Promises, but it seems like you're binding to a regular object. You can just remove both async keywords and it should probably work.

Upvotes: 53

Related Questions