I created 2 different collections (users and follow).
Now I want to:
Fetch document which exist inside the follow's collection("list") according by their id.
Fetch users data in the first collection where currentUid = doc.id (for the second collection).
Display data in the ListTile.
First collection
await FirebaseFirestore.instance.collection("users").doc(currentUid).set({"name":username,"photoUrl":url,"uid":currentUid});
Second collection
await FirebaseFirestore.instance.collection("follow").doc(currentUid).collection("list").doc(otherId);
I used this but it doesn't work properly
body:StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("follow")
.doc(user!.uid)
.collection("list")
.snapshots(),
builder: (context, snapshot1) {
if (!snapshot1.hasData) {
return Container();
} else {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("users")
.where("uid",
isEqualTo:
snapshot1.data!.docs.map((e) => e.id).toList())
.snapshots(),
builder: (context, snapshot2) {
if (!snapshot2.hasData) {
return Container();
} else {
return ListView(
children: snapshot2.data!.docs.map((e) {
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(e.get('url')),
radius: 30,
),
title: Text(e.get('username')),
);
}).toList(),
);
}
},
);
You should use the in query instead of the equal to query.
An in query returns documents where the given field matches any of the
comparison values.
The syntax for the in query in the cloud_firestore is this:
.where(field, whereIn: listOfFields)
Solution:
Change this:
.where("uid", isEqualTo: snapshot1.data!.docs.map((e) => e.id).toList())
to this:
.where("uid", whereIn: snapshot1.data!.docs.map((e) => e.id).toList())
Related
I have a collection called orders. In this I have a subcollection known as stockQuantity. Every day when new stock is added, the stock added that day along with the date are added as documents in the subcollection stockQuantity. I am trying to find the stock added on the latest date for each order and display it on a page known as StockPage, however nothing is being displayed on the page. The order must meet the criteria, orderStatus = 1.
An index has been created too.
This is my code for StockPage
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class StockPage extends StatefulWidget {
#override
State<StockPage> createState() => _StockPageState();
}
class _StockPageState extends State<StockPage> {
final Stream<QuerySnapshot> _stockStream = FirebaseFirestore.instance
.collection('orders')
.where("statusOrder", isEqualTo: 1)
.orderBy("stockQuantity.date", descending: true)
.snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Stock Quantity"),
),
body: StreamBuilder<QuerySnapshot>(
stream: _stockStream,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var stockQuantity = snapshot.data!.docs[index]["stockQuantity"].last;
return ListTile(
title: Text(stockQuantity["quantity"].toString()),
subtitle: Text(stockQuantity["date"].toString()),
leading: Text('${snapshot.data!.docs.length}'),
);
},
);
}),
);
}
}
Nothing is being displayed on the page.
I tried using print statements to find the values of different variables, but none of them showed the stock quantity
Error text:
Null check operator used on a null value The relevant error-causing
widget was StreamBuilder<List>
ChangeNotifierProvider(
create: (context) => getIt<ModelCreator>(),
child: StreamBuilder(
stream: getIt<ModelCreator>().chatList(),
builder: (context, AsyncSnapshot<List<ChatModel>> snapshot) {
var _data = snapshot.data!; <- The error is here
return Container();
}),
),
There is no problem with empty Container, that part is full.
Thats getChatList() func
Stream<List<ChatModel>> getChatList() {
var data = _firebase
.collection('Users')
.doc(_fireauth.currentUser!.uid)
.collection('Chat List')
.orderBy('Last Message Date', descending: true);
return data.snapshots().map(
(event) => event.docs.map((e) => ChatModel.fromSnapshot(e)).toList());
}
Thats it ChatModel
factory ChatModel.fromSnapshot(
QueryDocumentSnapshot<Map<String, dynamic>> doc) {
return ChatModel(
id: doc.id,
image: doc['Image'],
phone: doc['Phone'],
photo: doc['Photo'],
username: doc['Username'],
createdDate: doc['Created Date'],
displayMessage: doc['Display Message'],
lastMessageDate: doc['Last Message Date'],
);
}
the snapshot data can be null. So before accessing the snapshot.data you should check
if(snapshot.hasData)
if it returns true, you can access the data without any issues
I'm making a to-do list with Flutter and Firebase Firestore, but I have a slight problem. Whenever I add a new task, snapshot.data becomes null. If I do not add a check for snapshot.connectionState and render a different widget according to that, I get the following error: NoSuchMethodError (NoSuchMethodError: The getter 'docs' was called on null.
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: SizedBox(
height: 100, width: 100, child: CircularProgressIndicator()),
);
} else {
> final docs = snapshot.data.docs;
return ListView.builder(
itemCount: docs.length,
itemBuilder: (ctx, index) {
final currTask = docs[index];
return Dismissible(
direction: DismissDirection.startToEnd,
key: UniqueKey(),
onDismissed: (_) async {
FirebaseFirestore.instance
.collection('tasks')
.doc(widget.uid)
.collection('mytasks')
.doc(currTask['id'])
.delete();
.
.
.
I don't want to have to display a CircularProgressIndicator or an empty screen. I want the tasks to remain visible and seamlessly add new tasks. How can I achieve that? I know what I asked for in the question title might be a little silly, what should I do instead?
I'm trying to use where in a Firebase firestore query in my flutter application but it is showing all the data in the collection without filtering it ., here is my code :
Widget buildingMessages() {
print('message room id $roomID'); //The correct id is being printed here
var theMessages = FirebaseFirestore.instance.collection('messages');
theMessages.where('room_id',isEqualTo: roomID).orderBy('created', descending: true);
return StreamBuilder<QuerySnapshot>(
stream: theMessages.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
return new ListView(
children: snapshot.data.docs.map((DocumentSnapshot document) {
//....
The problem is in stream: theMessages.snapshots(). You are referencing the theMessages. and you are not using your where clause. extends it with your where clause. like
stream: theMessages.snapshots().where(
'room_id',isEqualTo: roomID).orderBy('created', descending: true);
Edit: Or initialize it as
var theMessages = FirebaseFirestore.instance.collection('messages').
where('room_id',isEqualTo: roomID).orderBy('created', descending: true);
Here, I'm trying to print the username of the user and it produces the following error.
I created a function userData() and the code is
userData() async
{
var userData = await _db.collection('users').document(_uuid).get();
return userData;
}
Where I'll just get the data of the specific user using uid and returning it.
The code I used to print the data is as follow
return FutureBuilder(
future: authService.userData(),
builder: (_,snapshots){
if(snapshots.connectionState == ConnectionState.waiting)
{
return Center(child: Text('Loading...'),);
}
else{
print("Snapshots: "+snapshots.toString());
return ListView.builder(itemCount: 1, itemBuilder: (_,index){
return ListTile(
title: Text(snapshots.data["username"].toString()),
);
});
}
}
);
The structure of firestore is
Collection('user') -> document(uid) -> 1.username 2.email ....
What is the reason for this error and how to resolve it?
The error message is telling you that snapshots.data is null, so you can't index into it with the [] operator.
Before using a DocumentSnapshot, you should check to see if it exists before accessing its field data. The snapshot's data property will be null if the document doesn't exist.
For Firestore I would recommend using Stream Builder rather than future Builder.
return StreamBuilder(
stream: Firestore.instance
.collection('user')
.document(uid)
.snapshots(),
builder: (_,snapshot){
if(!snapshot.hasData)
{
return Center(child: Text('Loading...'),);
}
else{
return ListView.builder(itemCount: 1, itemBuilder: (_,index){
return ListTile(
title: Text(snapshots.data["username"].toString()),
);
});
}
}
);