I have code in flutter where I am filtering data based on userId. But I also want that data to be sorted based on descsending order based on date. Like I want to show current day data first and then for previous date. In firestore its feasible while I am finding it hard to do with realtime. Below is code snippet where I have added query to filter by userId. Below I want to add sort data based on dates as well(I am saving timestamp)
_database.reference().child("node name here..").orderByChild("userId").
equalTo("my user id here...").once().then((snapshot )async{}
FirebaseDatabase returns oldest data first ,In order to view latest data i would suggest you reverse the list or whilst saving your timestamp * by -1 to make document "oldest"
example
int time = DateTime.now().microsecondsSinceEpoch;
var timestamp = time * -1;
you can query your data as per this example
return StreamBuilder(
stream: FirebaseDatabase.instance
.reference()
.child('node')
.orderByChild('userid')
.equalTo(userId)
.onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.snapshot.value != null) {
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
List<dynamic> list = map.values.toList();
return ListView.builder(
itemCount: list.length,
padding: EdgeInsets.all(4.0),
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(13),
child: Container(
decoration:
BoxDecoration(color: Colors.blueGrey[100]),
child: ListTile(
title: Text(list[index]["title"]),
subtitle: Text(list[index]["text"]),
),
PS
watch for you console to see if you get a link to create an index
Related
I'm trying to retrieve from my collection "Courses" 2 field.
Course code and Course name. My issue when retrieving is that I only managed to retrieve the first field.
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.separated(
itemCount: snapshot.data!.docs.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(height: 1),
// ignore: dead_code
itemBuilder: (context, index) {
DocumentSnapshot doc = snapshot.data!.docs[index];
return ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 30, vertical: 10),
selectedTileColor: Color(0xffE5E5E5),
title: Text.rich(
TextSpan(
text: doc["Course code"],
children: <TextSpan>[
TextSpan(text: ":"),
TextSpan(text: doc["Course name"]),
and it shows me this error:
Exception has occurred.
StateError (Bad state: field does not exist within the DocumentSnapshotPlatform)
this is my firebase
I only can retrieve course code I don't know why.
It seems like you have a problem with how Flutter and Firebase interacts with each other. I would like to suggest to check the following threadand especially the comment posted by jschnip which could solve your problem
This is probably related to recent changes in DocumentSnapshot, your
factory is looking for the data map, which used to be in doc, but nows
its in doc.data() - except DocumentID
So for your factory, one way to change it would be to adjust to:
Userr( id: doc.id, email: docdata['email'], username:
docdata['username'], url: docdata['url'], profileName:
docdata['profileName'], bio: docdata['bio'], subject1:
docdata['subject1'], subject2: docdata['subject2']
and when you call
it, you'll need to do something like:
doc.data();
newUserrr = Userr.fromDocument(doc, _docdata);
In my App I use a Streambuilder to show a list of plans that are stored in Firestore (every plan has its own document) on a screen:
final CollectionReference planCol = FirebaseFirestore.instance.collection('users').doc(FirebaseAuth.instance.currentUser.uid).collection('plans');
body: StreamBuilder(
stream: planCol.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final planDocs = snapshot.data.docs;
return ListView.builder(
itemCount: planDocs.length,
itemBuilder: (context, index) => MyListTile(
title: Text(planDocs[index]['name']),
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () {
edit(planDocs[index]);
},
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ExerciseTable(
plan: UserPlan(
name: planDocs[index]['name'],
exerciseNames: planDocs[index]
['exerciseNames'],
rows: planDocs[index]['rows'],
planId: planDocs[index].id,
),
);
},
),
);
}),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}));
On this screen, I only want to show the name of each document and not all the other data which is stored in the document(because they are very big). Now I was asking myself how efficient Streambuilder works when each document is very big. Does it load the whole document or only the field of the document, that is needed?
On this screen I only want to show the name of each document and not all the other data which is stored in the document(because they are very big).
All Cloud Firestore listeners fire on the document level. So there is no way you can get only the value of a single field in a document. That's the way Firestore works.
Now I was asking myself how efficient Streambuilder works when each document is very big.
It's more about the time that it takes to download those documents.
Does it load the whole document or only the field of the document, that is needed?
It loads the entire document.
If you need only some names, you should consider storing those names in a single document. In this case, you can read only one document and you have to pay only one read.
I am new to firebase and I am wondering how would you access specific data. Ill give you an example, BTW I am using flutter.
Say I am creating data like this. I making a table of posts or I guess in firebase it'd be just a json array. In this json array I have 4 pieces of data state, city, post which as of right now just represents a simple message, and also timestamp.
So my question is how can I get a filtered version of my posts with a given city and state? Is there something special you can do in firebase? or would I have to do the filtering when I am building the list view?
I know FirebaseDatabase().reference().child('posts'); can access all of the posts.
var _firebaseRef = FirebaseDatabase().reference().child('posts');
_firebaseRef.push().set({
"state": state,
"city": city,
"post": post,
"timestamp": DateTime.now().millisecondsSinceEpoch
});
The code in the question means you are adding data, not retrieving. If you want to retrieve data according to a specific city then do the following query:
var dbRef = FirebaseDatabase().reference().child('posts');
dbRef.orderByChild("city").equalTo("city_name").once();
once() returns a Future so you can use the FutureBuilder to get the data from the above query.
Use Future Builder to fetch data to listview
create getPost() method first to return qn
Future getPosts() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection("your_collecttion_name").getDocuments();
return qn.documents;
}
after that use, future builder to fetch data
return Container(
child: FutureBuilder(
future: getPosts(),
builder: (_, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Text("Loading..."),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return Column(
children: <Widget>[
Text(
snapshot.data[index].data['your_data_field'] //name,age etc..
.toString(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500),
),]
),}
),
});
I'm building an app in Flutter in which I have data stored in the Firebase Realtime Database. I want to fetch those data in my app.
Now, Because of breaking changes made few months ago I'm unable to find new articles or video which might help but all I find are old ones so if anyone here can help me?
variable for the list
final dbRef = FirebaseDatabase.instance.reference().child("workshops");
now for showing the data I'm trying like this
return FutureBuilder(
future: dbRef.once(),
builder: (context,AsyncSnapshot<DataSnapshot> snapshot){
if(snapshot.hasData){
workshopList.clear();
Map<dynamic, dynamic> values = snapshot.data.value;
values.forEach((key,values){
workshopList.add(values);
});
}
return ListView.builder(
shrinkWrap: true,
itemCount: workshopList.length,
itemBuilder: (BuildContext context, index){
return Card(
child: Center(
child: Column(
children: [
Text("name "+ workshopList[index].workshopName)
],
),
),
);
},
);
}
);
For declaring list I was doing like this
List<Workshop> worskshopList = [];
but what worked for me was
List<Map<dynamic,dynamic>> workshopList = [];
And now for showing the data I am using
workshopList[index].workshopName
now problem with this is that I am not referencing database's workshopname but my model class' workshop name so I am getting nowhere.
now what worked for me was
workshopList[index]["workshopname"]
now from the old list I can't use like list[index][""] it will give an error like "[]" is not defined for the list.
Currently my code is grabbing the order of the listed values by how it is indexed and i'm passing it to my raw sql query. I think i may be going about this the wrong way buy using listviewbuilder, but I want to grab the primary key (from sqlite database) of the clicked on value and pass that to the query on the next page
body: !loading ? new ListView.builder(
itemCount: sectorList.length,
itemBuilder: (BuildContext context, int index) {
return new Card(
color: Colors.cyan[800],
elevation: 2.0,
child: new ListTile(
title: new Text("${sectorList[index]}"),
onTap: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) =>
DocumentPage(id: index),
),
);
}),
);
},
) : CircularProgressIndicator(),
);
}
}
any help or guidance would be greatly appreciated.
Comment if you need to see more of the code.
You must be using some type of query like:
List<Map<String, dynamic>> categories =
await db.rawQuery('SELECT * FROM tbl_categories order by category_name');
This is going to give you a List with each of the categories ordered by name. If the table also contains another column (maybe category_id) that will also be available in the map.
Now each ListTile looks like:
child: new ListTile(
title: new Text("${categories[index]['category_name']}"),
onTap: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) =>
OtherPage(id: categories[index]['category_id']),
),
);
},
),
You display the name, but pass the id to the next page. Assuming then that there's another table with a foreign key of category_id you could:
await db.rawQuery('SELECT * FROM tbl_other WHERE category_id=${widget.id}');
This would give you another List<Map<String, dynamic>> of all the other things in the relevant category. Use this to build this next page.