filter data from firebase in flutter - firebase

in my system there are notices which have both status 'approved' and 'unapproved'. I want to display only 'unapproved'notices and I want to convert them 'approved' by using flutter app.
this is the screenshot of my firebase.
by using below codes I can display notice all notice list
Widget build(BuildContext context) {
final notices = Provider.of<List<Notice>>(context) ?? [];
return StreamBuilder<List<Notice>>(
stream: NoticeService().notices,
builder: (context, snapshot) {
if(snapshot.hasData){
return GridView.builder (
itemCount: notices.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 1),
// ignore: missing_return
itemBuilder: (context,index){
return SingleNotice(
notice:notices[index]
);
}
);
}else{
return(Text('No List'));
}
}
);
}
i create notice stream like this
final CollectionReference noticeCollection=Firestore.instance.collection('Notices');
//notice list from snapshot
List<Notice>_noticeListFromSnapshot(QuerySnapshot snapshot){
return snapshot.documents.map((doc){
return Notice(
title:doc.data['title'] ?? '',
url: doc.data['url'] ?? '',
category: doc.data['noticecategory'] ?? 'General',
status: doc.data['status'] ?? 'unapproved',
dateTime: doc.data['dateTime'] ?? '',
noticeId: doc.data['noticeId'] ?? ''
);
}).toList();
}
Stream<List<Notice>>get notices{
return noticeCollection.snapshots().map(_noticeListFromSnapshot);
}
then how can I filter unapproved notices and display them.

To get only the unapproved documents, you can use a query:
final CollectionReference noticeCollection=Firestore.instance.collection('Notices');
final Query unapproved = noticeCollection.where("status", isEqualTo: "unapproved")
And then use that in place of the collection in:
Stream<List<Notice>>get notices{
return unapproved.snapshots().map(_noticeListFromSnapshot);
}

Related

WhereIn limit in flutter firebase

I am building an app and I'm trying to show all of the posts in the feed page of the people the current user is following.
It's working well, but my problem is the WhereIn limit.. How can I evade this limitation inside a FutureBuilder?
here is the code:
buildFeed() {
return FutureBuilder(
future: storiesRef
.where('uid', whereIn: widget.userIds)
.orderBy('timeStamp', descending: true)
.get(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return loading();
}
final stories = snapshot.data.docs;
List<StoryTickets> tickets = [];
for (var story in stories) {
List<String> categories = List.from(story.data()['categories']);
StoryTickets ticket = StoryTickets(
displayName: story.data()['displayName'],
categories: categories,
storyId: story.data()['sid'],
commentId: story.data()['cid'],
ownerId: story.data()['uid'],
rating: story.data()['rating'].toString(), //TODO: maybe delete
storyPhoto: story.data()['storyPhoto'],
timestamp: story.data()['timeStamp'],
title: story.data()['title'],
);
tickets.add(ticket);
}
return ListView(
children: tickets,
);
},
);
}

How can i get data from firebase by document ID in Flutter? [duplicate]

Edit: This Question is outdated, and I am sure, new documentation and more recent answers are available as of now.
I want to retrieve data of only a single document via its ID. My approach with example data of:
TESTID1 {
'name': 'example',
'data': 'sample data',
}
was something like this:
Firestore.instance.document('TESTID1').get() => then(function(document) {
print(document('name'));
}
but that does not seem to be correct syntax.
I was not able to find any detailed documentation on querying firestore within flutter (dart) since the firebase documentation only addresses Native WEB, iOS, Android etc. but not Flutter. The documentation of cloud_firestore is also way too short. There is only one example that shows how to query multiple documents into a stream which is not what i want to do.
Related issue on missing documentation:
https://github.com/flutter/flutter/issues/14324
It can't be that hard to get data from a single document.
UPDATE:
Firestore.instance.collection('COLLECTION').document('ID')
.get().then((DocumentSnapshot) =>
print(DocumentSnapshot.data['key'].toString());
);
is not executed.
but that does not seem to be correct syntax.
It is not the correct syntax because you are missing a collection() call. You cannot call document() directly on your Firestore.instance. To solve this, you should use something like this:
var document = await Firestore.instance.collection('COLLECTION_NAME').document('TESTID1');
document.get() => then(function(document) {
print(document("name"));
});
Or in more simpler way:
var document = await Firestore.instance.document('COLLECTION_NAME/TESTID1');
document.get() => then(function(document) {
print(document("name"));
});
If you want to get data in realtime, please use the following code:
Widget build(BuildContext context) {
return new StreamBuilder(
stream: Firestore.instance.collection('COLLECTION_NAME').document('TESTID1').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new Text("Loading");
}
var userDocument = snapshot.data;
return new Text(userDocument["name"]);
}
);
}
It will help you set also the name to a text view.
Null safe code (Recommended)
You can either query the document in a function (for example on press of a button) or inside a widget (like a FutureBuilder).
In a method: (one time listen)
var collection = FirebaseFirestore.instance.collection('users');
var docSnapshot = await collection.doc('doc_id').get();
if (docSnapshot.exists) {
Map<String, dynamic>? data = docSnapshot.data();
var value = data?['some_field']; // <-- The value you want to retrieve.
// Call setState if needed.
}
In a FutureBuilder (one time listen)
FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
future: collection.doc('doc_id').get(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text ('Error = ${snapshot.error}');
if (snapshot.hasData) {
var data = snapshot.data!.data();
var value = data!['some_field']; // <-- Your value
return Text('Value = $value');
}
return Center(child: CircularProgressIndicator());
},
)
In a StreamBuilder: (always listening)
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: collection.doc('doc_id').snapshots(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text('Error = ${snapshot.error}');
if (snapshot.hasData) {
var output = snapshot.data!.data();
var value = output!['some_field']; // <-- Your value
return Text('Value = $value');
}
return Center(child: CircularProgressIndicator());
},
)
If you want to use a where clause
await Firestore.instance.collection('collection_name').where(
FieldPath.documentId,
isEqualTo: "some_id"
).getDocuments().then((event) {
if (event.documents.isNotEmpty) {
Map<String, dynamic> documentData = event.documents.single.data; //if it is a single document
}
}).catchError((e) => print("error fetching data: $e"));
This is simple you can use a DOCUMENT SNAPSHOT
DocumentSnapshot variable = await Firestore.instance.collection('COLLECTION NAME').document('DOCUMENT ID').get();
You can access its data using variable.data['FEILD_NAME']
Update FirebaseFirestore 12/2021
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('YOUR COLLECTION NAME')
.doc(id) //ID OF DOCUMENT
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new CircularProgressIndicator();
}
var document = snapshot.data;
return new Text(document["name"]);
}
);
}
This is what worked for me in 2021
var userPhotos;
Future<void> getPhoto(id) async {
//query the user photo
await FirebaseFirestore.instance.collection("users").doc(id).snapshots().listen((event) {
setState(() {
userPhotos = event.get("photoUrl");
print(userPhotos);
});
});
}
Use this code when you just want to fetch a document from firestore collection , to perform some operations on it, and not to display it using some widget (updated jan 2022 )
fetchDoc() async {
// enter here the path , from where you want to fetch the doc
DocumentSnapshot pathData = await FirebaseFirestore.instance
.collection('ProfileData')
.doc(currentUser.uid)
.get();
if (pathData.exists) {
Map<String, dynamic>? fetchDoc = pathData.data() as Map<String, dynamic>?;
//Now use fetchDoc?['KEY_names'], to access the data from firestore, to perform operations , for eg
controllerName.text = fetchDoc?['userName']
// setState(() {}); // use only if needed
}
}
Simple way :
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('YOUR COLLECTION NAME')
.doc(id) //ID OF DOCUMENT
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new CircularProgressIndicator();
}
var document = snapshot.data;
return new Text(document["name"]);
}
);
}
var document = await FirebaseFirestore.instance.collection('Users').doc('CXvGTxT49NUoKi9gRt96ltvljz42').get();
Map<String,dynamic>? value = document.data();
print(value!['userId']);
You can get the Firestore document by following code:
future FirebaseDocument() async{
var variable = await FirebaseFirestore.instance.collection('Collection_name').doc('Document_Id').get();
print(variable['field_name']);
}
Use this simple code:
Firestore.instance.collection("users").document().setData({
"name":"Majeed Ahmed"
});

How to acces data from StreamProvider Flutter

I'm trying to show a list of reminder where user see all their reminders and able to edit it. I'm using StreamProvider so that I'm able to access in child widget. I map the DocumentSnapShot into MedReminder object. The StreamProvider should return List of MedReminder object. But in the ReminderList widget the Provider return null.
Stream:
List<MedReminder> _medReminderListFromSnapshot(QuerySnapshot snapshot) {
print('here is db');
return snapshot.documents.map((doc) {
return MedReminder(
remindId: doc.data['remindId'] ?? '',
howManyTimeDay: doc.data['howManyTimeDay'] ?? '',
frequency: doc.data['frequecy'] ?? '',
hour: doc.data['hour'] ?? '',
min: doc.data['min'] ?? '',
dateStarted: doc.data['dateStarted'] ?? '',
dateEnded: doc.data['dateEnded'] ?? '',
dateRefill: doc.data['dateRefill'] ?? '',
quantityTime: doc.data['quantityTime'] ?? '',
);
}).toList();
}
Stream<List<MedReminder>> get medReminders {
return userCollection.document(uid).collection('medic_reminder').snapshots()
.map(_medReminderListFromSnapshot);
}
Reminder Page:
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return StreamProvider<List<MedReminder>>.value(
value: DatabaseService(uid: user.uid).medReminders,
child: Scaffold(
body: Container(
child: ReminderList(),
),
),
);
}
Reminder List widget(here the provider returning null):
Widget build(BuildContext context) {
final reminders = Provider.of<List<MedReminder>>(context) ?? [];
reminders.forEach((reminder) {
print(reminder.remindId);
});
return ListView.builder(
itemCount: reminders.length,
itemBuilder: (context, index) {
return ReminderTile();
});
}
Please help me thanks.
Stream<List<MedReminder>> get medReminders {
return userCollection.snapshots()
.map(_medReminderListFromSnapshot);
}
Store Data In userCollection with uid, dont add other collections
like
collectionReference userCollection = Firestore.instance.collection('users');
when saving data in 'users'
userCollection.document(uid).setData()..
then it works

Flutter Stream Builder return only one LisTile from Firestore

I have a stream builder that is supposed to return a multiple LisTile but it returns only one, I have used the same structure with other collections and its work fine but for this collection it doesn't.
Widget build(BuildContext context) {
return StreamBuilder(
stream: DatabaseService().itemsCollection.snapshots(),
builder: ( context, snapshot){
if (!snapshot.hasData){
return Loading();
}
else{
List<Item> myItems= [];
for (int i=0; i<snapshot.data.documents.length; i++){
DocumentSnapshot snap = snapshot.data.documents[i];
myItems.add(
Item(
restaurantId: snap.data['restaurantId'],
id:snap.documentID ?? '',
name:snap.data['name']?? '',
price:double.tryParse(snap.data['price'].toString())?? 0,
calories:double.tryParse(snap.data['calories'].toString())?? 0,
section: MenuSection('','',''),
imageUrl:snap.data['imageUrl']?? '',
describtion: snap.data['describtion']?? '')
);
return
ListView.builder(
itemCount: myItems.length,
itemBuilder: (_, i) => Column(
children: [
ItemListItem(
id: myItems[i].id,
name: myItems[i].name,
describtion: myItems[i].describtion,
price: double.tryParse(myItems[i].price.toString()),
imageUrl: myItems[i].imageUrl,
// branchId: branchId,
restId: myItems[i].restaurantId ,
),
// Divider(),
], ),
);
}
}
}
);
Data in FireStore
If anyone can find where the issue please.
================= UPDATE =================
Issue Solved.
To whom might face this issue later,
I found the issue is that I have put the return statement inside the for loop, while it should after the loop ends!

Query a single document from Firestore in Flutter (cloud_firestore Plugin)

Edit: This Question is outdated, and I am sure, new documentation and more recent answers are available as of now.
I want to retrieve data of only a single document via its ID. My approach with example data of:
TESTID1 {
'name': 'example',
'data': 'sample data',
}
was something like this:
Firestore.instance.document('TESTID1').get() => then(function(document) {
print(document('name'));
}
but that does not seem to be correct syntax.
I was not able to find any detailed documentation on querying firestore within flutter (dart) since the firebase documentation only addresses Native WEB, iOS, Android etc. but not Flutter. The documentation of cloud_firestore is also way too short. There is only one example that shows how to query multiple documents into a stream which is not what i want to do.
Related issue on missing documentation:
https://github.com/flutter/flutter/issues/14324
It can't be that hard to get data from a single document.
UPDATE:
Firestore.instance.collection('COLLECTION').document('ID')
.get().then((DocumentSnapshot) =>
print(DocumentSnapshot.data['key'].toString());
);
is not executed.
but that does not seem to be correct syntax.
It is not the correct syntax because you are missing a collection() call. You cannot call document() directly on your Firestore.instance. To solve this, you should use something like this:
var document = await Firestore.instance.collection('COLLECTION_NAME').document('TESTID1');
document.get() => then(function(document) {
print(document("name"));
});
Or in more simpler way:
var document = await Firestore.instance.document('COLLECTION_NAME/TESTID1');
document.get() => then(function(document) {
print(document("name"));
});
If you want to get data in realtime, please use the following code:
Widget build(BuildContext context) {
return new StreamBuilder(
stream: Firestore.instance.collection('COLLECTION_NAME').document('TESTID1').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new Text("Loading");
}
var userDocument = snapshot.data;
return new Text(userDocument["name"]);
}
);
}
It will help you set also the name to a text view.
Null safe code (Recommended)
You can either query the document in a function (for example on press of a button) or inside a widget (like a FutureBuilder).
In a method: (one time listen)
var collection = FirebaseFirestore.instance.collection('users');
var docSnapshot = await collection.doc('doc_id').get();
if (docSnapshot.exists) {
Map<String, dynamic>? data = docSnapshot.data();
var value = data?['some_field']; // <-- The value you want to retrieve.
// Call setState if needed.
}
In a FutureBuilder (one time listen)
FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
future: collection.doc('doc_id').get(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text ('Error = ${snapshot.error}');
if (snapshot.hasData) {
var data = snapshot.data!.data();
var value = data!['some_field']; // <-- Your value
return Text('Value = $value');
}
return Center(child: CircularProgressIndicator());
},
)
In a StreamBuilder: (always listening)
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: collection.doc('doc_id').snapshots(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text('Error = ${snapshot.error}');
if (snapshot.hasData) {
var output = snapshot.data!.data();
var value = output!['some_field']; // <-- Your value
return Text('Value = $value');
}
return Center(child: CircularProgressIndicator());
},
)
If you want to use a where clause
await Firestore.instance.collection('collection_name').where(
FieldPath.documentId,
isEqualTo: "some_id"
).getDocuments().then((event) {
if (event.documents.isNotEmpty) {
Map<String, dynamic> documentData = event.documents.single.data; //if it is a single document
}
}).catchError((e) => print("error fetching data: $e"));
This is simple you can use a DOCUMENT SNAPSHOT
DocumentSnapshot variable = await Firestore.instance.collection('COLLECTION NAME').document('DOCUMENT ID').get();
You can access its data using variable.data['FEILD_NAME']
Update FirebaseFirestore 12/2021
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('YOUR COLLECTION NAME')
.doc(id) //ID OF DOCUMENT
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new CircularProgressIndicator();
}
var document = snapshot.data;
return new Text(document["name"]);
}
);
}
This is what worked for me in 2021
var userPhotos;
Future<void> getPhoto(id) async {
//query the user photo
await FirebaseFirestore.instance.collection("users").doc(id).snapshots().listen((event) {
setState(() {
userPhotos = event.get("photoUrl");
print(userPhotos);
});
});
}
Use this code when you just want to fetch a document from firestore collection , to perform some operations on it, and not to display it using some widget (updated jan 2022 )
fetchDoc() async {
// enter here the path , from where you want to fetch the doc
DocumentSnapshot pathData = await FirebaseFirestore.instance
.collection('ProfileData')
.doc(currentUser.uid)
.get();
if (pathData.exists) {
Map<String, dynamic>? fetchDoc = pathData.data() as Map<String, dynamic>?;
//Now use fetchDoc?['KEY_names'], to access the data from firestore, to perform operations , for eg
controllerName.text = fetchDoc?['userName']
// setState(() {}); // use only if needed
}
}
Simple way :
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('YOUR COLLECTION NAME')
.doc(id) //ID OF DOCUMENT
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new CircularProgressIndicator();
}
var document = snapshot.data;
return new Text(document["name"]);
}
);
}
var document = await FirebaseFirestore.instance.collection('Users').doc('CXvGTxT49NUoKi9gRt96ltvljz42').get();
Map<String,dynamic>? value = document.data();
print(value!['userId']);
You can get the Firestore document by following code:
future FirebaseDocument() async{
var variable = await FirebaseFirestore.instance.collection('Collection_name').doc('Document_Id').get();
print(variable['field_name']);
}
Use this simple code:
Firestore.instance.collection("users").document().setData({
"name":"Majeed Ahmed"
});

Resources