how to display properly single value from a StreamBuilder 'Cloud Firestore' - flutter

i have data stored in filds like so => image
i have followed the documentation, the data just refuses to show for some reason.
it looks somthing like this
StreamBuilder(
stream:
FirebaseFirestore.instance.collection('users').snapshots(),
builder: (context, snapshot) {....}
)
and then
if (snapshot.connectionState == ConnectionState.active) {
print(snapshot.data.documents[0]['User Email']);
....}
note: the stream works fine but im assuming this happening coz of the way im calling it the snapshot.data.documents
how can i properly call them ?

I think it is because of the [0].
When you read just one of the documents, refer to:
FirebaseFirestore.instance.collection('users').doc('yourDocument').snapshots();
and if you will read more then one you can use this:
CollectionReference users = FirebaseFirestore.instance.collection('users');
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return new ListTile(
title: new Text(document.data()['full_name']),
subtitle: new Text(document.data()['company']),
);
}).toList(),
);

Related

Flutter: CircularProgressIndicator not showing even though Stream returns no values

I have a StreamBuilder in order to get data from my user collection in Firestore to get their profile image. This works fine. But when for example I turn off my internet, then instead of showing a CircularProgressIndicator, it just shows my CircularAvatar with the backgroundColor.
Please see my code below. Normally when I turn off the internet, the code below should return the Progress Indicator. Why is that not happening? And when I then turn the internet back on, it does not update and show the correct profile image. Is the stream not working correctly?
StreamBuilder(
stream: DatabaseService(uid: uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(snapshot.data!.photoUrl),
),
);
} else {
return CircularProgressIndicator();

Need I do pagination for flutter StreamBuilder?

I'm new to flutter, and now I'm creating an app which has a feed page, I'm using StreamBuilder + firestore to do this, the code is like this:
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('posts')
.orderBy('createdAt', descending: true)
.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(
color: primaryColor,
),
);
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) => Container(
child: createPostViewFromSnapShot(snapshot.data!.docs[index]),// it returns a widget
),
);
},
);
You can see from the code I didn't do pagination, I want to know when the code runs, it fetch all the post from firestore ? Or it will fetch data by block or something like pagination ?
I want to know if it's necessary to do pagination for StreamBuilder?
Avoid creating Widgets in Methods. That way you cause your App to
become I'm-performant. Because the Widget is not sat directly in the
Tree, but a method, every build that methods gets called, no matter
if the resulting widget would have to be actually be rebuilt.
That stream will not always emit events where data is not null. You will most likely get an exception for using snapshot.data! bang operator
Take a closer look at the documentation: https://firebase.flutter.dev/docs/firestore/usage/
FlutterFire provides support for dealing with realtime changes to
collections and documents. A new event is provided on the initial
request, and any subsequent changes to collection/document whenever a
change occurs (modification, deleted or added).
For what you are trying to achieve, it would be better to initially fetch a limited set of documents from your collection.
collectionReference.limit(42).get()
You can than fetch the next elements by using https://firebase.flutter.dev/docs/firestore/usage/#start--end-cursors

Two StreamBuilderon on one screen with default empty screen shown when neither has data

I'm trying to create a Split View with two ListViews, one of them showing Tasks which are not completed and the second one containing completed tasks. I managed to make this work with a Column containing two Streambuilder. The problem I don't know how to solve is how to show a single default empty screen when neither of the two Streams have any values, due to the way Flutter works, I can't just return null. So I end up having two Empty default screens in my Column and on my screen.
What would be the right approach to make something like shown in the GIF with Firestore?
If I need to work with a single Stream and filter it inside dart, how can I make it work with ListView ?
I'd highly appreciate an example.
My Job class contains a boolean value jobDone which tells me in which list the Job has to go.
My current code:
return Column(
children: [
StreamBuilder<List<Job>>(
stream: getPendingJobsStream(database),
builder: (context, snapshot) {
return ListItemsBuilder<Job>(
...
);
},
),
ExpansionTile(
title: Text('Completed Tasks'),
children: [
StreamBuilder<List<Job>>(
stream: getCompletedJobsStream(database),
builder: (context, snapshot) {
return ListItemsBuilder<Job>(
...
);
},
),
],
),
],
);
You can check for snapshot state
builder: (context, snapshot) {
if(snapshot.connectionState ==ConnectionState.waiting){
return Center(child:CircularProgressIndicator();
}
if(snapshot.connectionState ==ConnectionState.done){
//check if snapshot has data
if(snapshot.hasData){
return ListItemsBuilder<Job>( ..

How to fetch the data from a List type of future call and a simple future call in one program in flutter

I have tried calling a list and a simple future in a single program and I also searched for this in the web I didn't get a solution
studentDetails.dart
Future<List<Stud>> studentDetails(http.Client client, var lin) async {
print(lin);
//Codes
return studList;
}
fetchhistory.dart
Future<AttendanceHistory> fetchhistory(http.Client client, String id) async {
//codes
return parsedJson;
}
I want these service file to be called in one component file.
studentView.dart
// Scaffold codes
body: FutureBuilder(
future: Future.wait([
studentDetails(http.Client(), widget.sid),
fetchhistory(http.Client(), widget.sid),
]),
builder: (context,AsyncSnapshot<List<dynamic>> snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
// lab: widget.label
? StudListView(
stud: snapshot.data[0],
his:snapshot.data[1]
)
: Center(child: CircularProgressIndicator());
},
),
//scaffold codes
Error Screenshot
I have the only problem in the implementation that how can I use 2 service calls inside the Body of the Scaffold Please help me because I am seriously tended to solve this error.
Thank you

Flutter - ReOrder Data Stored in FireStore

As you can see, I am dragging Tasks by using ReorderableListView widget of Flutter.
The onReorder is able to drag the tasks up and down. However, when I close the app, all of the tasks go in the default order as it was arranged.
This is because my data which is being fetched from the CloudFireStore isn't changing its order, the way is it updated in my dragging.
Can anyone help me, how can I update the position of tasks stored as documents in Cloud FireStore, so that when I close the app and open it again, it shows new updated positions and not old positions of the task
The code :
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("Tasks")
.doc(_email)
.collection("User_Tasks_List")
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text("Loading!...");
_docs = snapshot.data.documents;
return Theme(
data: ThemeData(canvasColor: Colors.transparent),
child: ReorderableListView(
children: _docs
.map((e) => InkWell(
key: ObjectKey(e),
onTap: () => _popupDialog(context, e),
onDoubleTap: () => FirebaseFirestore
.instance
.runTransaction(
(transaction) async {
transaction.delete(e.reference);
Fluttertoast.showToast(
msg: "Task has been deleted!");
}),
child: ViewHolder(e)))
.toList(),
onReorder: onReorder),
);
}),
You can add a parameter like index:x to items in firestore. Then you need to save the order of the ordered list items and store them in Firestore using the indexes.
When you fetch items you need to sort them by this index and you will get the same order.
objects.sort((a, b) => a.index.compareTo(b.index));