angular - 如何在 Angular(6) 和 firebase Firestore 设置中分页回到之前的页面

标签 angular firebase firebase-realtime-database pagination google-cloud-firestore

似乎有很多示例、教程和视频介绍如何在将 Angular 与 Cloud Firestore (Firebase) 结合使用时分页到下一页。

但经过大量搜索后,我找不到分页到上一页的方法。 我得到的最远只是返回到第一页。

这是我的服务现在的样子:

import { Injectable } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Task } from './task.model';

@Injectable()
export class TaskService {
  private _data: BehaviorSubject<Task[]>;
  public data: Observable<Task[]>;
  firstEntry: any;
  latestEntry: any;

  constructor(private afs: AngularFirestore) { }

  public first() {
    this._data = new BehaviorSubject([]);
    this.data = this._data.asObservable();

    const tasksRef = this.getCollection('tasks', ref => ref.orderBy('createdAt').limit(5))
      .subscribe(data => {
        this.firstEntry = data[0].doc;
        this.latestEntry = data[data.length - 1].doc;
        this._data.next(data);
      });
  }

  public next() {
    const tasksRef = this.getCollection('tasks', ref => ref.orderBy('createdAt').startAfter(this.latestEntry).limit(5))
      .subscribe(data => {
        if (data.length) {
          this.firstEntry = data[0].doc;
          this.latestEntry = data[data.length - 1].doc;
          this._data.next(data);
        }
      });
  }

  public previous() {
    const tasksRef = this.getCollection('tasks', ref => ref.orderBy('createdAt').endBefore(this.firstEntry).limit(5))
      .subscribe(data => {
        if (data.length) {
          this.firstEntry = data[0].doc;
          this.latestEntry = data[data.length - 1].doc;
          this._data.next(data);
        }
      });
  }

  private getCollection(ref, queryFn?): Observable<any[]> {
    return this.afs.collection(ref, queryFn).snapshotChanges().pipe(
      map(actions => {
        return actions.map(a => {
          const data = a.payload.doc.data();
          const id = a.payload.doc.id;
          const doc = a.payload.doc;
          return { id, ...data, doc };
        });
      })
    );
  }
}

初始加载(第一页)有效,所有下一页也按预期工作。 但似乎 endBefore(this.firstEntry) 没有保持正确的光标,并再次出现在第一页。

返回上一页的正确方法是什么?

如果有人知道完整的教程或工作分页器的示例,请分享...

最佳答案

import * as firebase from 'firebase/app';
import { last } from 'lodash';
import { dropRight } from 'lodash';

安装这个 npm 包(Lodash、Firebase)

从 lodash 导入 firebase、last 和 dropRight 后。 Last 方法返回数组的最后一个元素。 DropRight 方法对数组的最后一个元素进行切片。

allEntry: Array<any[]> =  [];
firstEntry = [];
lastEntry;

创建三个变量并将第一个条目分配给一个数组,以便在查询中存储第一个数据。 AllEntry 存储从查询中检索到的所有数据。 LastEntry 将最后一个元素存储在 allEntry 中,该元素将用作游标以获取之后的数据。

getMainEntry() {
return this.afs.collection('tasks', ref => ref.orderBy('createdAt').limit(5)).valueChanges().subscribe(data => {
  this.allentry = data;
  firebase.firestore().collection('tasks').doc(data[data.length - 1]['key']).onSnapshot(c => {
    this.lastentry = c;
    firebase.firestore().collection('tasks').doc(data[0]['key']).onSnapshot(da => {
      this.firstEntry.push(da);
    });
  });
});
}

这个getMainEntry函数获取集合中的数据,按createdAt排序,限制为5。然后获取allEntry数组中最后一个元素的documentsnapshot,并将其赋值给lastEntry。获取后将allEntry数组中第一个元素的documentsnapshot插入firstEntry数组。

现在让我们创建下一个函数

getNextData(){
  const entarr = [];
  firebase.firestore().collection('tasks').orderBy('createdAt').startAfter(this.lastEntry).limit(5).get().then((data) => {
    data.docs.map(a => {
      entarr.push(a.data());
      this.allEntry = entarr;
    });
  }).then(() => {
    firebase.firestore().collection('tasks').doc(entarr[entarr.length - 1]['key']).onSnapshot(data => {
      this.lastEntry = data;
    });
  }).then(() => {
    firebase.firestore().collection('tasks').doc(entarr[0]['key']).onSnapshot(da => {
      this.firstEntry.push(da);
    });
  });
}

getNextData 函数获取集合中的下一个数据,按createdAt 排序并限制为lastEntry 之后的下5 个数据。然后获取entarr数组中最后一个元素的documentsnapshot并将其赋值给lastEntry。获取后将allEntry数组中第一个元素的documentsnapshot插入firstEntry数组。

上一个函数

getPrevData() {
const entarr = [];
  this.firstEntry = dropRight(this.firstEntry);
const firstEntry = last(this.firstEntry);
firebase.firestore().collection('tasks').orderBy('createdAt').startAt(firstEntry).limit(5).get().then((d) => {
  d.docs.map(a => {
    entarr.push(a.data());
    this.allEntry = entarr;
    });
  }).then(() => {
    firebase.firestore().collection('tasks').doc(entarr[entarr.length - 1]['key']).onSnapshot(da => {
      this.lastEntry = da;
    });
  });
}

希望这会有用。

关于angular - 如何在 Angular(6) 和 firebase Firestore 设置中分页回到之前的页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51831193/

相关文章:

angular - ng e2e 测试超时

javascript - 在Angular 5中将AMP与Material Design Lite一起使用

javascript - FIrebase - 索引抛出错误和 OrderByChild 问题

android - Firebase 查询 limitToLast 无法按预期工作

javascript - Angular 自定义异步验证器不工作

node.js - 等待函数永远不会执行

android - 如何在 Firebase 数据库中搜索字符串中的任意位置 - Android

swift - 无法使用新的 Firebase 将类型 '__NSDictionaryM' 的值转换为自定义用户类

Swift:向 Firebase 变量添加值时如何修复无限循环

typescript - Angular2 (beta3) "expression has changed after it was checked"更新表单值