Ionic AngularFirebase Служба разбивки на страницы с бесконечной прокруткой

Я пытаюсь внедрить бесконечную прокрутку в свое приложение ionic angular. Будучи новичком в этом, мне нужен совет специалиста. Проблема в том, что функция more() работает в первый раз, когда происходит событие прокрутки, но переходит в бесконечный цикл при попытке получить второй набор документов. Вот код, я включил изображения компонента и html, а также полный сервис разбивки на страницы.

Компонент.ts:

  ngOnInit() {

      this.page.init('Documents', 'Name', { reverse: false, prepend: false })

  scrollHandler(e) {
      if (e === 'bottom') {
        this.page.more()
      }
     }

HTML шаблона:

<ion-infinite-scroll threshold="100px" (ionInfinite)="this.page.more($event)">
  <ion-infinite-scroll-content
    loadingSpinner="bubbles"
    loadingText="Loading more data...">
  </ion-infinite-scroll-content>
</ion-infinite-scroll>

разбиение на страницы-service.ts:

import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from  '@angular/fire/firestore';

import { BehaviorSubject } from 'rxjs';
import { map  } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { tap, scan, take} from 'rxjs/operators';


// Options to reproduce firestore queries consistently
interface QueryConfig {
  path: string, // path to collection
  field: string, // field to orderBy
  limit?: number, // limit per query
  reverse?: boolean, // reverse order?
  prepend?: boolean // prepend to source?
}

@Injectable()
export class PaginationService {

  // Source data
  private _done = new BehaviorSubject(false);
  private _loading = new BehaviorSubject(false);
  private _data = new BehaviorSubject([]);

  private query: QueryConfig;

  // Observable data
  data: Observable<any>;
  done: Observable<boolean> = this._done.asObservable();
  loading: Observable<boolean> = this._loading.asObservable();

  constructor( private afs: AngularFirestore ) { }

  // Initial query sets options and defines the Observable

  init(path, field, opts?) {

    this.query = { 
      path,
      field,
      limit: 10,
      reverse: false,
      prepend: false,
      ...opts
    }

    const first = this.afs.collection(this.query.path, ref => {
      return ref
             .orderBy(this.query.field, this.query.reverse ? 'desc' : 'asc')
              .where('Active', '==', 'Y')
               .limit(this.query.limit)             
    })

    this.mapAndUpdate(first)

    // Create the observable array for consumption in components
    this.data = this._data.asObservable()
        .pipe(scan( (acc, val) => { 
          return this.query.prepend ? val.concat(acc) : acc.concat(val)
        }))

  }

  // more() Retrieves additional data from firestore
// This works the first time but not the second time 

  more() {
    const cursor = this.getCursor()
    const more = this.afs.collection(this.query.path, ref => {
      return ref
              .orderBy(this.query.field, this.query.reverse ? 'desc' : 'asc')
              .limit(this.query.limit)
              .startAfter(cursor)
    })
     this.mapAndUpdate(more)
  }

  // Determines the doc snapshot to paginate query 
  private getCursor() {
    const current = this._data.value
    if (current.length) {
      return this.query.prepend ? current[0].doc : current[current.length - 1].doc 
    }
    return null
  }


  // Maps the snapshot to usable format the updates source
  private mapAndUpdate(col: AngularFirestoreCollection<any>) {

    if (this._done.value || this._loading.value) { return };

    // loading
    this._loading.next(true)

    // Map snapshot with doc ref (needed for cursor)
    return col.snapshotChanges()
      .pipe(tap(arr => {
        let values = arr.map(snap => {
          const data = snap.payload.doc.data()
          const doc = snap.payload.doc
          return { ...data, doc }
        })

        // If prepending, reverse array
        values = this.query.prepend ? values.reverse() : values

        // update source with new values, done loading
        this._data.next(values)
        this._loading.next(false)

        // no more values, mark done
        if (!values.length) {
           this._done.next(true)
        }
    }))
    .pipe(take(1))
    .subscribe()

  }

  // Reset the page
  reset() {
    this._data.next([])
    this._done.next(false)
  }
 }

person tomN    schedule 17.11.2019    source источник


Ответы (1)


Выражение, присвоенное событию ionInfinite, вызывается, когда пользователь достигает заданного расстояния. Когда это выражение завершит все задачи, оно должно вызвать метод complete() для экземпляра с бесконечной прокруткой.

В вашем случае вы не обработали событие, просто прошли...

this.page.more($event)

измените HTML-шаблон, как показано ниже:

<ion-infinite-scroll threshold="100px" (ionInfinite)="findNext($event)">

Добавьте метод в Component.ts:

async findNext($event) {
    setTimeout(async () => {
      await this.page.more();
      $event.target.complete();
    }, 500);
  }
person Prabhu Patil    schedule 11.11.2020