Getting QuerySnapshot instead of DocumentSnapshot [FLUTTER] - flutter

StreamBuilder(
stream: FirebaseFirestore.instance.collection('users').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
FirestoreUser firestoreUser =
FirestoreUser.fromDocument(snapshot.data); // Here snapshot.data is retrieving QuerySnapshot.
// How I can convert it to DocumentSnapshot
...
Hello StackOverflow users
I need to give to my new firestoreUser variable, which type of DocumentSnapshot. But I can't get it.
After writing snapshot.data it gives me an error called "QuerySnapshot is not subtype of DocumentSnapshot"
P.s I'm using StreamBuilder as you can see. Thank you

Your stream is FirebaseFirestore.instance.collection('users').snapshots() which is a QuerySnapshot, meaning, a List of QueryDocumentSnapshot which Extends DocumentSnapshot.
So if you want the documentSnapshot of every users in your 'users' collection, you will have to iterate over snapshot.data.docs:
But if you want to get the document of a particular user, then you can do:
StreamBuilder(
stream: FirebaseFirestore.instance.collection('users').doc(userID).snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
FirestoreUser firestoreUser =
FirestoreUser.fromDocument(snapshot.data);
...

Related

Flutter, How to use firebase query .orderBy() on timestamp data?

I have stored time stamp data in firebase, I am fetching it using streams and displaying it in the latest date order in a datatable widget. I used .orderBy to access descending bool. But neither true nor false worked, instead !snapshot.hasData condition is getting executed, Why orderBy is not working and what are the other queries that I can use to get the latest date order.
stream: FirebaseFirestore.instance
.collection('lender')
.doc(auth.currentUser!.email)
.collection('paymentData')
.where('name',
isEqualTo: Provider.of<UpdateNameProvider>(context,
listen: false)
.bname).orderBy('paidDate', descending: true)
.snapshots(),
//.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(
backgroundColor: Color(0xff8eacbb),
));
}
There are many possible reasons why a snapshot doesn't have data. At the very least you'll want to check if there's an error, and if so: log it somewhere.
Something like this:
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) { // 👈
return Text(snapshot.error); // 👈
}
...
Try like this.
FirebaseFirestore.instance
.collection('lender')
.doc(auth.currentUser!.email)
.collection('paymentData')
.orderBy('paidDate', descending: true).where('name',
isEqualTo: Provider.of<UpdateNameProvider>(context,
listen: false)
.bname)
.snapshots(),

How Can I Get Document name from AsyncSnapshot<QuerySnapshot>

The Goal
Get a document name from AsyncSnapshot<QuerySnapshot>
What I Did
In this collection users there is many documents which name is uid.
Using FutureBuilder and got AsyncSnapshot<QuerySnapshot>.
FutureBuilder(
future: FirebaseFirestore.instance
.collection("users")
.where('type', arrayContainsAny: ["Game", "Movie"])
.get(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
if (snapshot.connectionState == ConnectionState.done) {
String uid = ...... // Want to get document id (= uid)
By using this snapshot, it was possible to get fields of each documents.
But ofcourse these don't include their own name.
How can I get document id from AsyncSnapshot<QuerySnapshot>?
snapshot.data!.docs can contain zero, 1 or more documents matching the criteria. This is a list of document snapshots.
So for example the first result can be in snapshot.data!docs[0]. From here to get the document id (in your case uid) simply use snapshot.data!docs[0].id.

Use Futurebuilder to create a DropdownFormField Flutter?

I'm new to flutter and have a array in firestore. It's structure is:
Now i want to fetch that array, and use that array to build a dropdownFormfield.
My fetch Function is following:
fetchSchoolList() async {
List<dynamic> data = [];
Future<DocumentSnapshot<Object?>> result = schoolList.doc('List').get();
return result;
}
and my FutureBuilder is:
FutureBuilder<DocumentSnapshot<Object?>>(
future: fetchSchoolList(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState ==
ConnectionState.active) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
print(snapshot);
}
return Text('Loading List');
}),
But with this i'm even unable to get that array to print. I am getting error:
type 'Future' is not a subtype of type 'Future<DocumentSnapshot<Object?>>?'
Please help, i'm stuck here for days.#
There's a couple of things you could do:
First of all change fetchSchoolList() async {...} to something like this:
Future<DocumentSnapshot<List<String>?>>() async {
Future<DocumentSnapshot<List<String>?>> result =schoolList.doc('List').get();
return result;
}
Object isn't exactly a type, also flutter doesn't really know how to store information in with the type <Object>. Also you don't reference the data variable anywhere so it has been omitted.
Next change your FutureBuilder to something like this:
FutureBuilder<DocumentSnapshot<List<String>?>>(
future: fetchSchoolList(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.active) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
print(snapshot);
}
return Text('Loading List');
}),
This will specify what is being returned by the future (Basically the FutureBuilder's type) and because of that, you do not need to specify the snapshot type.

Firestore Class 'QuerySnapshot' has no instance method '[]'

I want a ListView to show the names of the users. I am using a cloudfunction with the admin sdk to return a list of all the users with the corresponding user IDs. When I want to pass that uid to a Widget with a streambuilder, it gives me the error:
Class 'QuerySnapshot' has no instance method '[]'.
Receiver: Instance of 'QuerySnapshot'
Tried calling: []("firstName")
This is the function I am calling while building the ListView for the title:
Widget getFirstName(uid, item) {
return StreamBuilder(
stream: Firestore.instance
.collection('users')
.document('HzBUMs06BAPHK0Y7m5kfOmUzawC2')
.collection('userInfo')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Text('${item['email']}');
} else {
return Text('${snapshot.data.documents['firstName']}');
}
},
);
}
I am not using the uid which I will pass to it yet, as the User ID that I hardcoded right now is the only one with the firstName data in it.
When I feed it a non-existing userID, it still seems to think it has data in it and tries to return its (non-existent) data.
What am I doing wrong here?
I managed to fix it by using this piece of code:
Widget fullNameWidget(uid) {
return FutureBuilder(
future: fullName(uid),
builder: (context, snapshot) {
return Text('${snapshot.data}');
},
);
}
Future fullName(uid) async {
return Firestore.instance
.collection("users")
.document('$uid')
.collection("userInfo")
.getDocuments()
.then((querySnapshot) {
print(querySnapshot.documents[0]['firstName']);
if (querySnapshot == 'null') {
} else {
return '${querySnapshot.documents[0]['firstName']} ${querySnapshot.documents[0]['lastName']}';
}
// querySnapshot.documents.where((element) {
// print(element.documentID == 'firstName');
// });
});
}

Flutter firestore streambuilder with a future

I have a simple question. The reference to my firestore collection is dynamic. In this piece of code, getDocumentReference() gives me a reference to document after checking the user's email.
I use this document reference to get my snapshots.
Future<Stream<QuerySnapshot>> getHabits() async {
DocumentReference document = await getDocumentReference();
var snapshots = document.collection('habits').snapshots();
return snapshots;
}
As you can see, I want to use this Future<Stream<QuerySnapshot>> for a streambuilder. How can I do that? I tried something like this. But it is not taking the future as input to stream
return StreamBuilder(
stream: getHabits(),
);
You can wrap it in a FutureBuilder:
return FutureBuilder<Stream<QuerySnapshot>>(
future: getHabits(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return StreamBuilder(stream: snapshot.data); // Success
} else if (snapshot.hasError) {
return Text('${snapshot.error}'); // Error
} else {
return CircularProgressIndicator(); // Loading
}
},
);