Error when extracting data from firebase into flutter app - flutter

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()

Related

How to let Flutter stream in streambuilder get limited document from firebase and accept new document created at the same time?

I am building an instant messaging app with flutter and firebase. I have a view to display user messages with a StreamBuider. The stream of the StreamBuider is accepting data from firebase. I have limited the number of messages loaded at a time for lazy loading purposes. The current problem is that when the user creates a new messages
For example, the original view has 3 messages (m1,m2,m3). When the user writes a new message (m4), the view will display (m2,m3,m4). m1 has gone. What I want is to keep all 4 messages. Is there a way to limit the number of documents gotten while listening on new documents?
StreamBuilder<QuerySnapshot>(
stream: messageService.getMessagesByChatIdStream(chatId),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
padding: EdgeInsets.all(10),
itemBuilder: (context, index) {
return buildMessageTile(index, snapshot.data?.docs[index]);
},
reverse: true,
itemCount: snapshot.data?.docs.length,
);
}
the getMessagesByChatIdStream() function is like this:
Stream<QuerySnapshot> getMessagesByChatIdStream(String chatId, {int limit = 5}) {
CollectionReference colRef =
firebaseFirestore.collection("messages").doc(chatId).collection(chatId);
return colRef
.limit(limit)
.orderBy('timestamp', descending: true)
.snapshots();
}

Flutter Firestore QuerySnapshot has no instance of getter 'documentID'

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.

Combine two stream-queries in flutter

I want to create a streambuilder to download multiple user-profiles from firebase. But to know which users are needed I have to get the user-ids at first, these are stored in an array. So I created a method to download the array and after this is done the streambuilder loads the user-data for each user-id from the array. Here's the code:
Method to get the array (executed in initState()):
Stream<QuerySnapshot> stream() async* {
job = Job.fromJson(await FirebaseFirestore.instance
.collection("jobs")
.doc(widget.jobId)
.get());
applicants = job.applicants;
await FirebaseFirestore.instance
.collection('users')
.where('uid', whereIn: applicants)
.snapshots();
}
And the streambuilder in the scaffolds' body:
body: isLoading
? Center(child: Container(child: CircularProgressIndicator()))
: applicants.isEmpty
? Center(
child: Text("no values"),
)
: StreamBuilder<QuerySnapshot>(
stream: stream(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else { xy }
So my question is if there's a possibility to combine the first method and the stream. Because at the moment the user can't get any update if an application is withdrawn while using the screen.

Flutter Fire Store - Assigning individual document fields to variables

I'm attempting to show a user's profile image on their home page by pulling the user's 'imageUrl' from their Fire Store document. I already have the app setup to where the user can upload a new image which updates the 'imageUrl' in Fire Store, but I don't know how to have the 'imageUrl' as a variable so I can show it on the app screen.
I've been reading documentation online but It seems over simplified or out of date. I've tried using StreamBuilder, but it pulls the data from every user in the database instead of for a single user. I just need to know how to pull this one value and use it as a variable in my dart code using "getString()" with a document reference or the collection reference I already have, thank you.
class _UserPageState extends State<UserPage> {
User user = auth.currentUser!;
final CollectionReference collectionReference = FirebaseFirestore.instance.collection('users');
// Get profileImageUrl from users userDoc
String imageUrl = 'test'; // this should be the users imageUrl
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'${user.email}'), // this is being pulled from authentication not firestore
),
body: Center(
child: Column(
children: [
// --------------------------- I tried using a stream builder here ---------------------
StreamBuilder(
stream: collectionReference.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text(
'Something went wrong.'); // A: use incase the data does not load
}
final data = snapshot.requireData;
return ListView.builder(
shrinkWrap: true,
itemCount: data.size,
itemBuilder: (context, index) {
return Text(
// A: Stream builder will update with all of the users email addresses, I want this for one user exclusively
'My email is ${data.docs[index]['email']}');
},
collection('users')
.where("uid", isEqualTo: uid)
.snapshots(),
To filter the data in firestore collection use "where". Store the user uid in offline and query it by where using the stored uid
You can use the following function to get single data from stream.
Stream<UserModel> getSingleStreamData({String? uId}) {
return ref!.where(CommonKeys.id, isEqualTo: uId).snapshots().map((value) => value.docs.first.data());}

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();
}
},
)