Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Firestore pagination

I'm trying to paginate by using Firestore and I read the document and it implement like this in Swift

let first = db.collection("cities")
    .order(by: "population")
    .limit(to: 25)

first.addSnapshotListener { (snapshot, error) in
    guard let snapshot = snapshot else {
        print("Error retrieving cities: \(error.debugDescription)")
        return
    }

    guard let lastSnapshot = snapshot.documents.last else {
        // The collection is empty.
        return
    }

    // Construct a new query starting after this document,
    // retrieving the next 25 cities.
    let next = db.collection("cities")
        .order(by: "population")
        .start(afterDocument: lastSnapshot)

    // Use the query for pagination.
    // ...
}

Just for practice, I tried fetched three documents and if button tapped, fetch one more document.

 Firestore.instance.collection('user').where('name', isEqualTo: 'Tom').orderBy('age').limit(3).getDocuments().then((snapshot) {
     _lastDocument = snapshot.documents.last;
     snapshot.documents.forEach((snap) {
        print(snap.data);
     });
   });

After button tapped tried like this.

 Firestore.instance.collection('user').where('name', isEqualTo: 'Tom').orderBy('age').startAfter(_lastDocument).limit(1).getDocuments().then((snapshot) {
     snapshot.documents.forEach((snap) {
        print(snap.data);
      });
     });

But console says this.

The following assertion was thrown while handling a gesture: type 'DocumentSnapshot' is not a subtype of type 'List[dynamic]'

Why do I have to pass list?

Does anyone know how to fix this?

UPDATE

I was able to paginate like so.

class PaginationExample extends StatefulWidget {
  @override
  _PaginationExampleState createState() => _PaginationExampleState();
}

class _PaginationExampleState extends State<PaginationExample> {
  var _restaurants = <Restaurant>[];
  var _nomore = false;
  var _isFetching = false;
  DocumentSnapshot _lastDocument;
  ScrollController _controller;


  void _fetchDocuments() async {
    final QuerySnapshot querySnapshot = await Firestore.instance.collection('restaurants').orderBy('likes').limit(8).getDocuments();
    // your logic here
  }

  Future<Null> _fetchFromLast() async {
    final QuerySnapshot querySnapshot = await Firestore.instance.collection('restaurants').orderBy('likes').startAfter([_lastDocument['likes']]).limit(4).getDocuments();
      if (querySnapshot.documents.length < 4) {
          _nomore = true;
          return;
      }
      _lastDocument = querySnapshot.documents.last;
      for (final DocumentSnapshot snapshot in querySnapshot.documents) {
        final Restaurant re = Restaurant(snapshot);
        _restaurants.add(re);
      }
      setState(() {});
  }

  void _scrollListener() async {
    if (_nomore) return;
    if (_controller.position.pixels == _controller.position.maxScrollExtent && _isFetching == false) {
        _isFetching = true;
        await _fetchFromLast();
        _isFetching = false;
    }
  }

@override
  void initState() {
    _fetchDocuments();
    _controller = new ScrollController()..addListener(_scrollListener);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(

    );
  }
}
like image 533
Daibaku Avatar asked Aug 07 '18 00:08

Daibaku


People also ask

What is pagination in firebase?

Pagination is the process of dividing data into discrete pages. In Firestore, it is achieved by ordering a collection by a field, limiting it to a consistent page size, then offsetting the query. The Firebase Web SDK v7. 3.0 introduced a new limitToLast(n) method that makes the process much easier.

What is FlutterFire?

FlutterFire is a set of Flutter plugins which connect your Flutter application to Firebase.

How do I get the last document in firestore?

Is there any way to get the last created document in Firebase Firestore collection? Yes, there is! The simplest way to achieve this is to add a date property to each object in your collection, then simply query it according to this new property descending and call limit(1) function. That's it!


2 Answers

There is an error here:

     Firestore.instance.collection('user').where('name', isEqualTo: 'Tom').orderBy('age').startAfter(_lastDocument).limit(1).getDocuments().then((snapshot) {
         snapshot.documents.forEach((snap) {
            print(snap.data);
          });
         });

startAfter method expects a List value params and you are passing a DocumentSnapshot.

Takes a list of [values], creates and returns a new [Query] that starts after the provided fields relative to the order of the query.

You could try something like this:

 Firestore.instance.collection('user').where('name', isEqualTo: 'Tom').orderBy('age').startAfter([{'name': 'Tom'}]).limit(1).getDocuments().then((snapshot) {
         snapshot.documents.forEach((snap) {
            print(snap.data);
          });
         });
like image 148
diegoveloper Avatar answered Oct 01 '22 00:10

diegoveloper


Paginate just with 2 attrubutes, itemBuilder and query using this package - paginate_firestore

For example,

      PaginateFirestore(
        itemBuilder: (context, documentSnapshot) => ListTile(
          leading: CircleAvatar(child: Icon(Icons.person)),
          title: Text(documentSnapshot.data['name']),
          subtitle: Text(documentSnapshot.documentID),
        ),
        // orderBy is compulsary to enable pagination
        query: Firestore.instance.collection('users').orderBy('name'),
      )
like image 41
Venkatesh Prasad Avatar answered Oct 01 '22 01:10

Venkatesh Prasad