This is the streambuilder im using to access all the documents at once
StreamBuilder(
stream: Firestore.instance.collection('projects').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('data is loading');
return ListView.builder(
itemBuilder: (ctx, index) {
return ProjectItem(
id: snapshot.data.documents[index]['id'],
title: snapshot.data.documents[index]['title'],
members: snapshot.data.documents[index]['members'],
complexity: snapshot.data.documents[index]['complexity'],
affordability: snapshot.data.documents[index]['affordability'],
duration: snapshot.data.documents[index]['duration'],
docid: snapshot.data.document[index].documentid,
);
},
itemCount: snapshot.data.documents.length,
}
Can i use docid: snapshot.data.document[index].documentid to access the document ids individually? if not whats the option? Thanks
You can make a custom Object constructor to use data from the document snapshot.
class ProjectItem {
String id;
String title;
String members;
String complexity;
String affordability;
String duration;
String docid;
ProjectItem({....});
factory ProjectItem.fromFirestore(DocumentSnapshot doc) {
return ProjectItem(
id: doc.data['id'],
title: doc.data['title'],
members: doc.data['members'],
complexity: doc.data['complexity'],
affordability: doc.data['affordability'],
duration: doc.data['duration'],
docid: doc.documentID,
);
}
}
And then just use this constructor inside the list view to make the object
return ProjectItem.fromFirestore(
snapshot.data.documents[index]
);
You can get the documentID this way
StreamBuilder(
stream: Firestore.instance.collection('projects').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('data is loading');
return ListView.builder(
itemBuilder: (ctx, index) {
QuerySnapshot snap = snapshot.data; // Snapshot
List<DocumentSnapshot> items = snap.documents; // List of Documents
DocumentSnapshot item = items[index]; Specific Document
return ProjectItem(
id: item.data['id'],
title: item.data['title'],
members: item.data['members'],
complexity: item.data['complexity'],
affordability: item.data['affordability'],
duration: item.data['duration'],
docid: item.documentID, // Document ID
);
},
itemCount: snapshot.data.documents.length,
);
},
),
)
THIS WORKED FOR ME:
StreamBuilder(
stream: Firestore.instance.collection('projects').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('data is loading');
return ListView.builder(
itemBuilder: (ctx, index) {
return ProjectItem(
id: snapshot.data.documents[index]['id'],
title: snapshot.data.documents[index]['title'],
members: snapshot.data.documents[index]['members'],
complexity: snapshot.data.documents[index]['complexity'],
affordability: snapshot.data.documents[index]['affordability'],
duration: snapshot.data.documents[index]['duration'],
docid: snapshot.data.documents[index].documentID,
);
},
itemCount: snapshot.data.documents.length,
);
Related
I'm trying to search for current chats in firestore by the user name but I get here all the chats I have even when I type a letter that is not included
Stream<QuerySnapshot<Map<String, dynamic>>> chatsSearchService(
String userId, String searchValue) {
return FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('chats')
.where('userName', isEqualTo: searchValue)
.snapshots();
I want to only get the chat which contains the letters I type
StreamBuilder(
stream: FirestoreServices()
.chatsSearchService('${cubit.userModel?.id}', cubit.searchValue),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snap) {
if (!snap.hasData) {
return Container();
}
return ListView.separated(
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
LastMessagesModel currentChats =
LastMessagesModel.fromJson(snap.data?.docs[index].data());
return InkWell(
child: searchChatBody(user, context, currentChats),
);
},
separatorBuilder: (context, index) {
return Divider();
},
itemCount: snap.data!.docs.length);
}),
This is my dataset :
I am trying to get this type of data in my app 1st I use an array and in the array i add map data and my value but i don't get any data.
My code
child: StreamBuilder(
stream: FirebaseFirestore.instance.collection("coin").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loder();
}
return ListView.builder(
itemCount: snapshot.data.document.length,
itemBuilder: (BuildContext context, int index) {
Map<dynamic, dynamic> map = snapshot.data.documents[index];
return ListTile(
title: Text(map.values.toList()[index]["coinlink"]),
);
},
);
}),
EDIT 1
I got this error I need data from coinlink title and img
The following NoSuchMethodError was thrown building StreamBuilder<QuerySnapshot<Map<String,
dynamic>>>(dirty, state: _StreamBuilderBaseState<QuerySnapshot<Map<String, dynamic>>,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>>>#29591):
Class '_JsonQuerySnapshot' has no instance getter 'document'.
How to get this type of data?
You need column inside list of display multiple coinLinks.
return ListView.builder(
itemCount: snapshot.data.document.length,
itemBuilder: (BuildContext context, int index) {
Map<dynamic, dynamic> map = snapshot.data.documents[index];
final coinLinks = map["coinLink"] as List<Map<String,dynamic>>;
return ListTile(
title: Column(
children: coinLinks.map((coinLink){
return Text(coinLink["title"]);
}).toList()
),
);
},
);
It does work cus i'm seeing
I/flutter (10071): [{quantity: 7, price: 4, name: Ayam Masah Merak, recipe: Ayam, Chilli, id: c5f935b0-538d-11eb-acb5-4d9f82c74017, category: food, picture: [https://firebasestorage.googleapis.com/v0/b/aizadfyp2021final.appspot.com/o/images%2F2021-01-10%2021%3A49%3A51.509046?alt=media&token=85605972-86da-4747-96ac-baa0abd5fe3a]}]
but at my phone it shows 'no data'. What did I do wrong? the code:
return FutureBuilder(
future: Global.productsRef.getData() , // this one too, yea
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
List<Product> products = snapshot.data;
return GridView.builder( // reload please, amazing
itemCount: products.length,
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return Single_prod(
prod_name: products[index].name,
prod_picture: products[index].picture[0],
prod_price: products[index].price,
product: products[index] ,
);
},
);
} else
return Text('no data');
});
I have an app which I want to display documents inside collection.. the collection reference is the uid of the user.
Is there a way to get current user uid and put this uid inside StreamBuilder in stream.
I have tried like so but it did not work and returned null:
class _MyAdsState extends State<MyAds> {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future getCurrentUser() async {
final FirebaseUser user = await _auth.currentUser();
final uid = user.uid;
print(uid);
return uid.toString();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("${getCurrentUser()}").snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> querySnapShot){
if(querySnapShot.hasError){
return Text('Some Error');
}
if(querySnapShot.connectionState == ConnectionState.waiting){
return CircularProgressIndicator();
}else{
final list = querySnapShot.data.documents;
return ListView.builder(
itemBuilder: (context, index){
return ListTile(
title: Text(list[index]["subject"]),
subtitle: Text(list[index]["category"]),
);
},
itemCount: list.length,
);
}
},
)
Getting the UID is an asynchronous operation, so requires a FutureBuilder.
If you want to use the UID to then build a stream, you'll need to have a FutureBuilder for the UID, and then inside of that a StreamBuilder for the stream from the database.
body: FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.hasData) {
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection(snapshot.data.uid).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> querySnapShot){
...
},
)
}
else {
return Text('Loading user data...');
}
THANK YOU GUYS!
I was looking for this for too long now. I had the "problem" that I was recording the senderUID for a sent message only, but of course wanted the Name being displayed in the "sentFrom" field. So I had to query Firestore for the UID and pull out the email. My solution:
FutureBuilder<QuerySnapshot>(
future: _firestore.collection("users").get(),
builder: (context, futureSnapshot) {
if (!futureSnapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
Map<String, String> users = {};
final userData = futureSnapshot.data.docs;
for (var user in userData) {
users[user.id] = user.data()["email"];
}
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection("messages").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
// ignore: missing_return
final messages = snapshot.data.docs;
List<Widget> messageWidgets = [];
for (var message in messages) {
final messageText = message.data()["text"];
final messageEmail = users[message.data()["senderUID"]];
messageWidgets
.add(Text("$messageText from $messageEmail"));
}
return Column(children: messageWidgets);
},
);
},
),
I just created a map from the data and used it inside the stream builder. Is there maybe a better solution?
buildComments() {
return StreamBuilder(
stream: commentRef
.document(postId)
.collection('comments')
.orderBy('timestamp', descending: false)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
List<Comment> comments = [];
snapshot.data.documents.forEach((doc) {
print(comments);
comments.add(Comment.fromDocument(doc));
});
return ListView(
children: comments,
);
});
}
I was trying to convert it in list view.builder but it gives me error you can can't use list instead of Widget, Can anyone solve this problem.
You should do the following:
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.all(8.0),
title: Text(snapshot.data.documents[index].data["name"]),
);
});
Assuming you have name in the document.