Flutter: How to loop through each field in `DocumentSnapshot.data()`

Viewed 3296

I have a collection where each user has their own document. In the document I create a map for a new entry. The document would look something like this: Sample Document

In my app, I want to get the document and then turn it into a list where each map (titled by the time) would be an entry. I tried looping through it but the problem is that there is not a forEach() in the DocumentSnapshot.data() and it is a type of _JsonDocumentSnapshot.

How can I get this as a List where 2021-05-30 20:49:59.671705, 2021-05-30 20:50:00:600294, ... are individual elements in a list. I plan on building each entry on its own using something such as a ListView.builder() so I would like to have a list of all those entries.

Edit: My code looks something like this:

journal is just a DocumentReference.

journal.snapshots().forEach((element) {
      var data = element.data();
      print(element.data());

      (data ?? {}).forEach((key, value) {
        return JournalEntryData(
            date: key,
            entryText: value['entryText'],
            feeling: value['feeling']);
      });
    });
3 Answers

The problem was that the type of data which was set to element.data() was Object? hence the forEach() method wasn't defined. I tried casting the element.data() as a List which caused errors so I didn't go further down that path. What I should have done was to cast element.data() as a Map which worked. I also should have used journal.get() and not snapshots() as it is a stream so the await keyword would result in the journal.snapshots().forEach() to never end.

The final code looked something like this:

Future<List<JournalEntryData>> getJournalEntries() async {
  List<JournalEntryData> entries = [];

  await journal.get().then((document) {
    Map data = (document.data() as Map);
    data.forEach((key, value) {
      print('adding entry');
      entries.add(JournalEntryData(
        date: key,
        entryText: value['entryText'],
        feeling: value['feeling'],
      ));
    });
  });

  return entries;
}

and I would do the following to get the entries:

var entries = await getJournalEntries();

Hey for most of my problems like these I choose to go with this approach;

final result = await _db
          .collection("collectionName")
          .get();

      List<Object> toReturn = [];
      for (int i = 0; i < result.docs.length; i++) {
       // add data to list you want to return.
        toReturn.add();
          }

Hopefully, this will be helpful to you.

List collectionElements = [];

void messagesStream() async {
  await for (var snapshot in _firestore.collection('your collection').snapshots().where(
          (snapshot) => snapshot.docs
              .every((element) => element.author == currentUser.id),
        )) {
    collectionElements.add(snapshot);
  }
  print(collectionElements);
}

Each element would be added to the collectionElements list.

If you want to access only one field in your snapshot this works fine:

final entryText= element.data()['entryText'];
print(entryText); // this would print "lorem ipsum..."
Related