Search code examples
angularfirebaseangularfire2

angular/fire get next item in collection using startAfter


I am having trouble getting the next item in a collection using angular/fire.

The error I am getting is:

Error: Function startAfter() called with invalid data. Unsupported field value: a custom AngularFirestoreDocument object

Based on these Firebase docs I think startAfter() wants a DocumentSnapshot but I don't know how to convert AngularFirestoreDocument to DocumentSnapshot and whilst the angular/fire docs mention startAfter they do not give any code examples.

Here's my problem code. I want the first document in the collection after the video document.

getNextVideo$(id: string, group: string): Observable<IVideo> {

  const video: AngularFirestoreDocument<IVideo> = this.afs.doc<IVideo>(`videos/${id}`)

  const collection: AngularFirestoreCollection<IVideo> = this.afs.collection<IVideo>('videos', ref => {
    return ref
      .where('group', '==', group)
      .where('flowPlayerProcessed', '==', true)
      .orderBy('timeCreated')
      .startAfter(video) // <<<<< ERROR IS HERE
      .limit(1)
  })

  return collection.valueChanges().pipe(
    map((videos: IVideo[]) => videos.length ? videos[0] : null)
  )
}

Solution

  • OK this rather verbose monstrosity works

    getNextVideo$(id: string, group: string): Observable<IVideo> {
    
      const video: AngularFirestoreDocument<IVideo> = this.afs.doc<IVideo>(`videos/${id}`)
    
      return video.snapshotChanges().pipe(
        switchMap((videoSnapshotAction: Action<DocumentSnapshot<IVideo>>) => {
    
          const videoSnapshot: DocumentSnapshot<IVideo> = videoSnapshotAction.payload
    
          const collection: AngularFirestoreCollection<IVideo> = this.afs.collection<IVideo>('videos', ref => {
            return ref
              .where('group', '==', group)
              .where('flowPlayerProcessed', '==', true)
              .orderBy('timeCreated')
              .startAfter(videoSnapshot)
              .limit(1)
          })
          return collection.valueChanges().pipe(
            map((videos: IVideo[]) => videos.length ? videos[0] : null)
          )
        })
      )
    }