1
votes

I've inadvertently changed some code somewhere and now my posts are no longer being pulled through, can anyone spot the mistake?

Service:

  posts: AngularFirestoreCollection<any[]>;

  constructor(private db: AngularFirestore) { }

  getPosts() {
    this.posts = this.db.collection('/posts') as AngularFirestoreCollection<any[]>;
    return this.posts;
  }
}

Post Component:


  posts: AngularFirestoreCollection<any>;

  constructor(private firebaseService: FirebaseService) { }

  ngOnInit() {
    this.posts = this.firebaseService.getPosts();
  }

}

Post HTML:

  <mat-grid-tile *ngFor="let post of posts">
      <mat-card class="mat-elevation-z4">
          <img mat-card-image src="{{post.imgUrl}}">
          <mat-card-actions>
              <button mat-icon-button><mat-icon>thumb_up_alt</mat-icon></button><span class="counter mat-small">{{post.numberOfLikes}}</span>
              <button mat-icon-button><mat-icon>star</mat-icon></button><span mat-small class="counter mat-small">{{post.numberOfSaves}}</span>
          </mat-card-actions>
      </mat-card>
  </mat-grid-tile>
</mat-grid-list>``

Now I'm getting Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

1
try *ngFor="let post of posts | async"Ashish Ranjan
Thanks but now I get. InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'FullerPrime
<img mat-card-image src="{{post[0].imgUrl}}">kashif
can you show response from this.db.collection('/posts') as AngularFirestoreCollection<any[]>?porgo
As per the OP question and comments in the below answers, for sure he is getting object instead of Array. That is why you are getting ngfor only supports binding to iterables. Check the response of service call and content of posts to resolve the issueGangadhar JANNU

1 Answers

2
votes

Here are some suggestions to fix your problem:

  1. AngularFirestoreCollection should be passed the item type of your collection, here you an array type (any[]), but something like Post would be more appropriate.
  2. You have to call valueChanges() or snapshotChanges() on your collection to get an observable of it. this.db.collection('/posts') only returns a reference to the collection (an object to manage it) and not the list itself.
  3. Then use the async pipe in the template to automatically subscribe/unsubscribe from the returned observable.

In your service:

export interface Post {
  imgUrl: string;
  numberOfLikes: number;
  numberOfSaves: number;
}

@Injectable()
export class FirebaseService {
  postsRef: AngularFirestoreCollection<Post>;

  constructor(private db: AngularFirestore) { }

  getPosts() {
    this.postsRef = this.db.collection('/posts') as AngularFirestoreCollection<Post>;
    return this.postsRef.valueChanges();
  }
}

In your component:

import { Observable } from 'rxjs';
import { FirebaseService, Post } from '....';

@Component({ ... })
export class MyComponent implements OnInit {
  posts$: Observable<Post[]>;

  constructor(private firebaseService: FirebaseService) { }

  ngOnInit() {
    this.posts$ = this.firebaseService.getPosts();
  }
}

In your template:

<mat-grid-tile *ngFor="let post of posts$ | async">
  ...
</mat-grid-list>