I want to sort the posts in my application by date, but when I use orderby I get a null check operator used on a null value error. The problem is that when I type 'where' together with 'orderby' there is a problem.
My code below:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('posts')
.where('uid', isEqualTo: widget.uid)
.orderBy(
'datePublished',
descending: true,
)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
primary: false,
shrinkWrap: true,
itemCount: (snapshot.data! as dynamic).docs.length,
itemBuilder: (context, index) {
DocumentSnapshot snap =
(snapshot.data! as dynamic).docs[index];
Firestore is an optimized database. As a result, you have to create composite indexes for complex queries, like the one you are doing (combining orderBy with where), to work.
To solve this problem, look at the logs where you are running Flutter. you should see a Firebase Console link that will take you straight to creating the query. Create the query, wait for 5 minutes or less for it to build, then try the code again. It should work.
because stream can be return null value then snapshot.data! as dynamic make error. Please check snapshot.hasData
Add 1 more condition
if (snapshot.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
}
Related
I want to display groups with this condition
current user id must include in the members array of group collection
order by LastUpdate (time)
So, I used steam like this
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groups")
.orderBy('LastUpdate', descending: true)
.where(
"members",
isEqualTo: FirebaseAuth.instance.currentUser!.uid,
)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: const TextStyle(color: Colors.white),
);
}
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.only(top: 5),
child: ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
return Text(
snapshot.data.docs[index]['groupName'],
style: const TextStyle(fontSize: 40, color: Colors.white),
);
},
),
);
} else {
return const Center(
child: CircularProgressIndicator(color: Colors.white),
);
}
});
When I run first time, It showed error and said,
FAILED_PRECONDITION: The query requires an index. You can create it here: ...
I created it. there is picture of it,
With this, Application run without error. But,
When I use .where( "members",isEqualTo: FirebaseAuth.instance.currentUser!.uid,), It not display anything. empty without any error.
(There are 3 groups, this user id has in the member's array - its sure. I checked it correctly)
When I remove .where( "members",isEqualTo: FirebaseAuth.instance.currentUser!.uid,) from snapshot. It working properly.
What can I do to fix this. HELP
If members is an array in a document, you must use "arrayContains" not "isEqualTo"
.where(
"members",
arrayContains: FirebaseAuth.instance.currentUser!.uid,
)
I tried printing firebase data using stream, but instead of the data I got this in terminal " [ ] ". This means the data is null. But there is data in firebase, how do I solve this problem.
firebase's data
stream builder
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('paymentData')
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return const Center(
child: Text('Loading'),
);
}
print(snapshot.data!.docs);
return ListView(
children: snapshot.data!.docs.map((data) {
return ListTile(
title: Text(data['amount']),
);
}).toList());
},
),
Based on your firebase structure, there is no path called paymentData, it is actually a nested sub-collection, so in order to reach paymentData, you need to also include the parent of that collection, like this:
stream: FirebaseFirestore.instance
.collection('lender').doc(yourLenderId).collection('paymentData')
.snapshots(),
Get the lender ID from a previus step, which is the id of the document
So Im trying to make a Screen which it will close when the return from api is empty
here's the code i've been trying to
FutureBuilder(
future: GetOrga(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.data == null){
return Container(
child: Center(
child: CircularProgressIndicator(
color: Colors.red,
)
)
);
}
return ListView.builder(
itemCount: snapshot.data == null ? 0 : snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
if (snapshot.data == ""){
Navigator.pop(context);
}
return GestureDetector()
but it doesn't seem to work, It load and when the loading finished it just show empty screen.
here's the Flutter Output
flutter: []
I would recommend you used the method hasData of the AsyncSnapshot class which corresponds to your snapshot:
if (!snapshot.hasData) {
Navigator.pop(context)
}
I would also recommend you checked the snapshot.connectionState prop before accessing the data, as there may be an error or it may still be waiting for the response.
Update
Now that you've posted your API response, the condition snapshot.data == '' will never be true as it returns a list. You should use snapshot.data == [] or cast it to a list and use the isEmpty operator.
I am building a one to one chat app using Flutter and firebase and I want to display all the chats under label of the day on which it happened,like it is on all major chat apps.
I retrieve data from firestore in ascending order of time by using order by command on the timestamp field of each message and as suggested by NiklasLehnfeld
i used groupBy method in the collection package to group my messages and used nested list view builders outer one for creating groups and inner one for filling those groups with data.
Here is the code
Widget build(BuildContext context) {
return FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (ctx, futureSnapshot) {
if (futureSnapshot.connectionState == ConnectionState.waiting) return Center(child: CupertinoActivityIndicator());
return StreamBuilder(
stream: Firestore.instance
.collection('mychats/${futureSnapshot.data.uid}/${widget.recieverUid}')
.orderBy('createdAt', descending: true)
.snapshots(),
builder: (context, chatSnapshots) {
if (chatSnapshots.connectionState == ConnectionState.waiting)
return Center(child: CupertinoActivityIndicator());
else {
final List chatDocs = chatSnapshots.data.documents;
Map<String, List> grouped = groupBy(chatDocs, (chat) {
String dateTime = chat['dateTime'];
return dateTime;
});
(grouped.forEach((m, v) {
print('$m');
for (int i = 0; i < v.length; i++) {
print(v[i]['text']);
}
}));
return ListView.builder(
reverse: true,
itemCount: grouped.keys.length,
itemBuilder: (ctx, index1) {
String date = grouped.keys.toList()[index1];
List messages = grouped[date];
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(date),
ListView.builder(
reverse: true,
primary: false,
shrinkWrap: true,
itemCount: messages.length,
itemBuilder: (context, index) {
return MyMessageBubble(
chatDocs[index].documentID,
chatDocs[index]['text'],
(chatDocs[index]['userId'] == futureSnapshot.data.uid) ? true : false,
ValueKey(chatDocs[index].documentID));
})
],
);
});
}
},
);
},
);
}
This is the list of messages that I am fetching
This is the UI .The results that i am printing in console are not displaying correctly in UI.I tried setting keys for both the list builders but no success. Is there any way it can be corrected
You are using the wrong list:
This:
chatDocs[index].documentID,
chatDocs[index]['text'],
(chatDocs[index]['userId'] == futureSnapshot.data.uid) ? true : false,
ValueKey(chatDocs[index].documentID));
should reference messages, not chatDocs. Because index is the index into messages.
the documentId is not work
chatDocs[index]['text'],
chatDocs[index]['userId'] == futureSnapshot.data.uid,
key: ValueKey(chatDocs[index].id),
just use only id
Hi I have a simple query for Firestore in a StreamBuilder
StreamBuilder(
stream: FirestoreManager.firebaseFirestore
.collection("orders")
.orderBy('logs.0', descending: true)
.where('status', whereIn: current['id'])
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snap) {
print(snap.data.toString());
if (!snap.hasError && snap.hasData) {
QuerySnapshot snapshot = snap.data;
if (snapshot.documents.isNotEmpty) {
List<DocumentSnapshot> snapList = snapshot.documents;
return ListView.builder(
padding: EdgeInsets.only(right: 10, left: 10),
physics: ScrollPhysics(),
itemCount: snapList.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return OrderListItem(
order: Order.fromJson(snapList[index].data),
);
},
);
} else {
return Center(
child: Text(
"No ${current['status'].toString().trim()} Order Available...!",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
);
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
})
It works absolutely fine for mobile appilcaiton but when I try to run it for web, It doesn't work.
Actually it shows data once for a second and again disappears. I got following log in console by printing snapshot data using print(snap.data.toString());
js_primitives.dart:30 null
js_primitives.dart:30 Instance of 'QuerySnapshot'
js_primitives.dart:30 null
Why is this happening? Why it shows data once and again disappear it?
If I remove either .orderBy('logs.0', descending: true) or .where('status', whereIn: current['id']) then it works fine.
I am having the same problem with flutter web. I am trying to use two chained where() methods and it doesn't give me any results:
StreamBuilder(
stream: fire
.collection('thiHistory')
.where("device", "==", _device)
.where("ts", '>=', ts)
.onSnapshot,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return Text('Loading....');
final docs = snapshot.data.docs;
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: docs.length,
itemBuilder: (context, index) {
final doc = docs[index].data();
return doc["device"] == _device ? Column(
children: [
Text(doc['device']),
Text("${doc["hour"]}"),
Text("${doc["temp"]}"),
Text("${doc["humi"]}"),
Text("${doc["thi"]}"),
],
) : Container();
});
},
)
If I only use one where() or the other it works fine. If I use both, I always get "Loading....", which tells me the snapshot has no data.
I also tried chaining orderedBy() with where() like Shahzad Akram, and same thing... Using one or the other works great, combining them does not return data.
I am using the firebase 7.3.0 package and version 7.19.1 of the libraries:
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-firestore.js"></script>
Thanks for your help.