Flutter Firestore QuerySnapshot has no instance of getter 'documentID' - flutter

I get an error that "QuerySnapshot that has no instance of getter 'documentID'".
StreamBuilder(
stream: FirebaseFirestore.instance.collection("CHAT").orderBy("createdAt",descending: true).snapshots(),
builder: (ctx,AsyncSnapshot snapshot){
if(snapshot.connectionState==ConnectionState.waiting)
{
return Center(child: CircularProgressIndicator(color:Colors.green[300]));
}
else {
var doc=snapshot.data!.docs;
var user=FirebaseAuth.instance.currentUser;
return ListView.builder(
reverse: true,
itemCount: doc.length,
itemBuilder: (BuildContext ctx,index){
return BubbleMessage(
key: ValueKey(doc[index].documentID),
//:::::::::::::::get Message From firebase :::::::::::
message:doc[index]['message'],
//we check if the id isMe or the Other Person
isMe: doc[index]['userId']==user!.uid,
//::::::::::::::get username From Firebase ::::::::::::::::::
username: doc[index]['username'],
);
},
);
Why am I unable to access the documentID?

The getter of the ID is just .id, not .documentID. See here. I'd recommend using your IDE's autocomplete to see what getters are available.
In the majority of cases the documentation on Flutter packages are extremely well documented and visible from within your IDE.

Related

Error when extracting data from firebase into flutter app

I want to ask for some help or advice.
I have a simple form which stores data in Firebase.
I created a new page where I want to display that information. I am using StreamBuilder to display the data for the logged user.
return Scaffold(
appBar: AppBar(
title: const Text("Your upcoming appointments"),
),
body: SafeArea(
child: Column(
children: [
StreamBuilder(
stream: FirebaseFirestore.instance.collection('client_bookings_doc').where('email', isEqualTo: currentUser.currentUser!.email).snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
shrinkWrap: true,
itemBuilder: (context, i) {
var data = snapshot.data!.docs[i];
print(data['email']);
return Text(data['email']);
},
);
} else {
return const Text("error");
}
},
),
],
),
),
);
I don't understand why I am getting that error:
W/GooglePlayServicesUtil( 3777): .................. requires the Google Play Store, but it is missing.
E/GooglePlayServicesUtil( 3777): GooglePlayServices not available due to error 9
W/Firestore( 3777): (24.4.2) [GrpcCallProvider]: Failed to update ssl context: com.google.android.gms.common.GooglePlayServicesNotAvailableException
I was following a few tutorials online and they both work fine.
Any help will be appreciated.
Update: I changed the device to google pixel 2 and now the error is
W/ProviderInstaller( 5334): Failed to report request stats: com.google.android.gms.common.security.ProviderInstallerImpl.reportRequestStats [class android.content.Context, long, long]
This query doesn't match the document structure in your screenshot:
FirebaseFirestore.instance
.collection('client_bookings_doc')
.where('email', isEqualTo: currentUser.currentUser!.email)
.snapshots()
There is no collection client_bookings_doc in your screenshot. Instead there is a root collection client_bookings with a document client_bookings_doc and then a subcollection again named client_bookings.
If you want to query across all client_bookings collection, you can use a collection group query:
FirebaseFirestore.instance
.collectionGroup('client_bookings') // 👈
.where('email', isEqualTo: currentUser.currentUser!.email)
.snapshots()

uid is not defined for type 'Object' in flutter

i am trying to check if a user id is the same as the current user's id by using data.uid but i keep getting this error:
The getter 'uid' isn't defined for the type 'Object'.
this is the code
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.value(FirebaseAuth.instance.currentUser),
builder: (context, futureSnapshot){
if(futureSnapshot.connectionState == ConnectionState.waiting){
return Center(child: CircularProgressIndicator(),);
}
return StreamBuilder <QuerySnapshot>(
stream: firestore.collection('chats').orderBy('timeStamp', descending: true).snapshots(),
builder:(ctx, chatSnapshot){
if(chatSnapshot.connectionState == ConnectionState.waiting){
return Center(child: CircularProgressIndicator(),);
}
final chatdocs = chatSnapshot.data!.docs;
return ListView.builder(
reverse: true,
itemCount: chatdocs.length ,
itemBuilder: (ctx, index) => messageBubble(
chatdocs[index]['text'],
chatdocs[index]['userId'] == futureSnapshot.data!.uid, //this is the error
)
);
}
);
} );
Since you don't declare the type of the Future in your FutureBuilder, it resolves to an Object. And an Object doesn't have a uid property, which is why you get the error.
To solve this declare the type of your FutureBuilder, which in your case would be:
return FutureBuilder<User>(
Note that I have no idea why you're using a FutureBuilder here to begin with. The FirebaseAuth.instance.currentUser is a synchronous value, so you don't need a FutureBuilder to access it. Removing the FutureBuilder would lead to the exact same result.
If you're trying to make your code respond to auth state changes, like that it takes a moment for Firebase to restore the user's sign-in state when you start the app, you'll want to actually listen to authStateChanges with a StreamBuilder for that nowadays, as shown in the first code snippet in the documentation on getting the current user. Here too, you'll want to declare your StreamBuilder with a User type, just like we did above for the FutureBuilder.
You can try json decoding your variable into the object User you are looking for:
If the futureSnapshot.data is a user you'll be able to use the uid as a map key to check with chatdocs[index]['userId']
Like this:
import 'dart:convert';
final Map<String, dynamic> _valueMap = json.decode(futureSnapshot.data!);
chatdocs[index]['userId'] == _valueMap['uid'];
Try the following code:
StreamBuilder<QuerySnapshot>(
stream: firestore.collection('chats').orderBy('timeStamp', descending: true).snapshots(),
builder: (ctx, chatSnapshot) {
if (chatSnapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
final List<QueryDocumentSnapshot<Object?>> chatdocs = chatSnapshot.data!.docs;
final String uid = FirebaseAuth.instance.currentUser?.uid ?? '';
return ListView.builder(
reverse: true,
itemCount: chatdocs.length,
itemBuilder: (ctx, index) {
final Map<String, dynamic> chat = (chatdocs[index]).data() as Map<String, dynamic>;
return messageBubble(
chat['text'],
chat['userId'] == uid,
);
},
);
},
),

Fetching data properly with Futurebuilder and json response

How can I render my response in my text widget?
My json snapshot.data is as following:
"{\"0\":{\"Breed\":\"American Hairless Terrier\",\"count\":1},\"1\":{\"Breed\":\"Bolognese\",\"count\":2},\"2\":{\"Breed\":\"Cavalier King Charles Spaniel\",\"count\":12},\"3\":{\"Breed\":\"Central Asian Shepherd Dog\",\"count\":1},\"4\":{\"Breed\":\"Papillon\",\"count\":1}}"
I tried to display my data like this:
Text(snapshot.data[index.toString()]['Breed']),
but I am getting:
type 'String' is not a subtype of type 'int' of 'index'
try this, might not be perfect but i will give you some idea, the error is because you are assigning int value to Text widget
Text((snapshot.data[index].
['Breed']).toString());
if you want to show it in
futureBuilder and listview
here:
FutureBuilder(
future: FirebaseFirestore.
instance.
collection("groups").
doc(groupId).snapshots(),
//here your collection name
// and doc id
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return Text("Loading");
}
var userDocument = snapshot.data["Breeds"];
return ListView.builder(
itemCount: userDocument.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Text(userDocument[index]);
),
}
);
The indices 0,1,2,3.. are strings(wrapped with quotation marks). But you are providing int.
Try
Text(snapshot.data['Breed'][index.toString()])

Why am I getting this error Bad state: field does not exist within the DocumentSnapshotPlatform while using firestore?

Bad state: field does not exist within the DocumentSnapshotPlatform
The relevant error-causing widget was
StreamBuilder<QuerySnapshot<Object?>>
StreamBuilder:file:///D:/EgoPro/Flutter%20Apps/task_app/lib/screens/task_screen.dart:189:13
this is the error
StreamBuilder<QuerySnapshot>(
// <2> Pass `Stream<QuerySnapshot>` to stream
stream:
FirebaseFirestore.instance.collection('tasks').snapshots(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
// <3> Retrieve `List<DocumentSnapshot>` from snapshot
final List<DocumentSnapshot> documents = snapshot.data!.docs;
print(documents);
return ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: documents
.map(
(doc) => Meetingcard(
id: doc.get("id"),
title: doc.get("title"),
description: doc.get("description"),
time: TimeOfDay.now()),
)
.toList());
} else if (snapshot.hasError) {
return Text("'It's Error!'");
} else {
return CircularProgressIndicator();
}
},
)
Why am i getting this error ?
This is the image of my documents
enter image description here>
doc.get will return this error if the specified field does not exists in the document. So one of your fields: id, title, description (or more of these) can't be found in doc.
You can add a breakpoint or log and check the result of doc.data() inside your .map((doc)... to see what does it contain.
(One of the possible ways to handle optional fields is to define a model class, create converter where you handle missing values and assign empty string or other default value, so when you read data from your stream you can use this model, and you don't have to handle missing values there.)
EDIT:
Based on the error picture in comment the error seems to be somewhere else, where you assign value to documents. snapshot.data!.docs has the type List<QueryDocumentSnapshot<Object?>> and not `List. Try the following code:
StreamBuilder<QuerySnapshot>(
// <2> Pass `Stream<QuerySnapshot>` to stream
stream:
FirebaseFirestore.instance.collection('tasks').snapshots(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
// <3> Retrieve `List<DocumentSnapshot>` from snapshot
return ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: snapshot.data!.docs
.map(
(DocumentSnapshot doc) => Meetingcard(
id: doc.data()!["id"],
title: doc.data()!["title"],
description: data()!["description"],
time: TimeOfDay.now()),
)
.toList());
} else if (snapshot.hasError) {
return Text("'It's Error!'");
} else {
return CircularProgressIndicator();
}
},
)

AsyncSnapshot rejecting Type Annotation

I have a StreamBuilder that is taking data from my bloc component.
However it keeps rejecting my type annotation AsyncSnapshot<List<int>> snapshot and only accepts dynamic as a type AsyncSnapshot<List<dynamic>> snapshot. Yet in the examples i've viewed they do have type annotaions with no complaints.
Here is my stream creation.
Widget buildList(StoriesBloc bloc) {
return StreamBuilder(
stream: bloc.topIds,
builder: (BuildContext context, AsyncSnapshot<List<int>> snapshot) {
if (!snapshot.hasData) {
return Text("Still Waiting for Ids to fetch");
}
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, int index) {
return Text('${snapshot.data[index]}');
},
);
},
);
}
Here is the VSCode error generated.
What could i be doing wrong ?
Turns out my bloc.topIds result type was not of type List<int>.
Observable<List> get topIds => _topIds.stream;
So i simply changed it to fulfill the required type.
Observable<List<int>> get topIds => _topIds.stream;
And that fixed the issue. Hope it helps someone else.