FutureBuilder can't "see" data / snapshot.hasData - firebase

I have a Future function to get data from Firebase, that is not empty queries correctly:
Future getProducts(vendorId) async {
await vendorsInfoColl.doc(vendorId)
.collection("products")
.get()
.then((QuerySnapshot querySnapShot) async {
if (querySnapShot.docs.isNotEmpty){
print('not empty');
print(querySnapShot.docs);
return querySnapShot.docs;
} else {
print('snapshot empty');
return null;
}
});
}
I just have trouble getting a FutureBuilder see it. Keeps saying there is empty data.
Widget build(BuildContext context) {
return AlertDialog(
// pull title from db
// title: Future Text(vendorTitle.toString()),
title: Text(vendorTitle.toString()),
content: FutureBuilder(
future: VendorDatabase().getProducts(widget.vendorId),
builder: (BuildContext context, AsyncSnapshot snapshot) {
print(snapshot.connectionState);
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
var blabla = snapshot.data;
print('there is snapshot data: $blabla');
return ListView.builder(
itemCount: 3,
itemBuilder: (context, index) {
return ListTile(
title: Text(blabla['products']) //<-- i know this is wrong but can't fixt it till future builder actually sees some data.
);
}
);
} else {
return const Text('Empty data');
}
} else {
return Text('State: ${snapshot.connectionState}');
}
}
)
);
}
It would be great if can also get some tips on how to put it in a list :)

You're not returning anything inside getProducts:
Future getProducts(vendorId) async {
return await vendorsInfoColl.doc(vendorId)
.collection("products")
.get()
.then((QuerySnapshot querySnapShot) async {
if (querySnapShot.docs.isNotEmpty){
return querySnapShot.docs;
} else {
return null;
}
});
}
To avoid this in the future, declare a type in your Future:
// vvvvvvvvvvvvvvvv
Future<List<Document>> getProducts(vendorId) async {

Related

Convert method into FutureBuilder : Flutter

I'm new to flutter. This is the method that I used to retrieve the data from firebase and I'm able to get the exact answer in the console. My question is how I can convert this code into future builder so I am able to read the data in my application.
void getUser() async {
firestoreInstance.collection("User Data").get().then((querysnapshot) {
querysnapshot.docs.forEach((result) {
firestoreInstance
.collection("User Data")
.doc(result.id)
.collection("bank")
.where('account_username', isEqualTo: ownerData?.name2)
.get()
.then((query Snapshot) {
querysnapshot.docs.forEach((result) {
print (result["bank_name"]);
});
});
});
});
}
You should return the value from the query, not print it
Your function should look like this
Future<String> getUser() async {
firestoreInstance.collection("User Data").get().then((querysnapshot) {
querysnapshot.docs.forEach((result) {
firestoreInstance
.collection("User Data")
.doc(result.id)
.collection("bank")
.where('account_username', isEqualTo: ownerData?.name2)
.get()
.then((query Snapshot) {
querysnapshot.docs.forEach((result) {
return result["bank_name"];
});
});
});
});
}
The Futurebuilder should look like this
FutureBuilder<String>(
future: getUser(), // async work
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting: return Text('Loading....');
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return Text('Result: ${snapshot.data}');
}

Flutter firestore sum all the field values according to daily record

I am new to flutter and firestore development. I have a collection of SalesRecord and a field name called SellingPrice. How can i sum all the value of SellingPrice according to everyday records and print out all those sum value.
Update Code :-
FutureBuilder(
future: FirebaseFirestore.instance.collection('SalesRecord').get(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> querySnapshot) {
if (querySnapshot.hasError) {
return Text("Something went wrong");
}
// if (snapshot.hasData && !snapshot.data!.exists) {
// return Text("Document does not exist");
// }
if (querySnapshot.connectionState == ConnectionState.done) {
querySnapshot.data!.docs.forEach((doc) {
sumTotal = sumTotal +
doc["SellingPrice"]; // make sure you create the variable sumTotal somewhere
});
return Text("Sum of all sells: ${sumTotal}");
}
return Text("loading");
},
),
Check out https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html and https://firebase.flutter.dev/docs/firestore/usage/ for detailed information. Following examples in there should bring you what you need.
For your case, you should use the builder inside the FutureBuilder try:
FutureBuilder(
future: FirebaseFirestore.instance
.collection('SalesRecord')
.get(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> querySnapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
querySnapshot.data!.docs.forEach((doc) {
sumTotal = sumTotal + doc["SellingPrice"]; // make sure you create the variable sumTotal somewhere
});
return Text("Sum of all sells: ${sumTotal}")
}
return Text("loading");
},
),

A value of type 'Object?' can't be assigned to a variable of type 'Tasker?'

Recently updated an existing and working flutter project to null safety but I cannot get my sign-in logic with firebase to work. It fails with the below error
A value of type 'Object?' can't be assigned to a variable of type 'Tasker?'.
Try changing the type of the variable, or casting the right-hand type to 'Tasker?'.
Widget _getScreenId() {
print('screen id');
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
Provider.of<UserData>(context, listen: false).currentUserId =
snapshot.data!.uid;
return FutureBuilder(
future: DatabaseService.getUserWithId(snapshot.data!.uid),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data);
Tasker? user = snapshot.data;
print("home");
return HomeScreen(user: user, currentUserId: '',);
}
return const SizedBox.shrink();
});
} else {
return const LoginScreen();
}
},
);
}
your snapshot by default returns a Object type try snapshot to AsyncSnapshot snapshot
Widget _getScreenId() {
print('screen id');
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context,AsyncSnapshot<Tasker> snapshot) {
if (snapshot.hasData) {
Provider.of<UserData>(context, listen: false).currentUserId =
snapshot.data!.uid;
return FutureBuilder(
future: DatabaseService.getUserWithId(snapshot.data!.uid),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data);
Tasker? user = snapshot.data;
print("home");
return HomeScreen(user: user, currentUserId: '',);
}
return const SizedBox.shrink();
});
} else {
return const LoginScreen();
}
},
);
}
ended up with this which seems to work
Widget _getScreenId() {
// print('screen id');
return StreamBuilder<User>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
Provider.of<UserData>(context, listen: false).currentUserId =
snapshot.data.uid;
return FutureBuilder(
future: DatabaseService.getUserWithId(snapshot.data.uid),
builder: (context, snapshot) {
if (snapshot.hasData) {
Tasker user = snapshot.data;
// print("home");
return HomeScreen(currentUserId: user.id, user: user);
}
return const SizedBox.shrink();
});
} else {
return const LoginScreen();
}
},
);
}

Flutter - Class 'DocumentSnapshot' has no instance getter 'docs'

I have 2 streams in my codes the first one is to get the userid from friend list and the second stream is to use the list of ids to search for the userid's document in firebase.
Stream friendIDStream;
Stream friendNameStream;
Widget friendList() {
return StreamBuilder(
stream: friendNameStream,
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
return FriendTile(
snapshot.data.docs[index].data()["username"]);
},
)
: Container();
},
);
}
#override
void initState() {
getUserFriend();
getNameByID();
super.initState();
}
getUserFriend() async {
Constant.currentId =
await HelperFunctions.getUserIdSharedPreference(Constant.currentId);
setState(() {
firebaseMethods.getFriend(Constant.currentId).then((value) {
setState(() {
friendIDStream = value;
});
});
});
}
getNameByID() {
setState(() {
firebaseMethods.getFriendName(friendIDStream).then((value) {
setState(() {
friendNameStream = value;
});
});
});
}
This is the firestore code.
Future getFriend(String ownerid) async {
return await FirebaseFirestore.instance
.collection("users")
.doc(ownerid)
.collection("friends")
.snapshots();
}
Future getFriendName(friendid) async {
return await FirebaseFirestore.instance
.collection("users")
.doc(friendid)
.snapshots();
}
I doesn't know why is this happening since I can display the list of ids. I had tried changing docs to doc but is also produce the same error.
Edit:
Added photos of my database structure.
the reason is your function getFriendName is returning a documentsnapshot not a querysnapshot. SO replace your old code with this:-
Widget friendList() {
return StreamBuilder(
stream: friendNameStream,
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: 1,
itemBuilder: (context, index) {
return FriendTile(
//snapshot.data.docs[index].data()["username"] old one
snapshot.data["username"]); //new one
},
)
: Container();
},
);
}

FutureBuilder's snapshot is always either null or has no data

I am fairly new to flutter and I hope this problem can be easily solved, but up until now I have no idea what's going wrong.
I have an app where I would like to return a list of users after the search button is pressed. I think that a FutureBuilder with a ListView.builder is the correct choice for this, but somehow I can't get my data to appear in the FutureBuilder even though my async function is definitely finding results.
My future:
Future<List<Map<dynamic, dynamic>>> results;
the button:
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
setState(() {
results = null;
searched = true;
});
results = getGuestData(widget.place['placeName'], query);
}
},
Async function:
Future<List<Map>> getGuestData(String placeName, Map query) async {
List<Map> result = [];
CollectionReference guestsRef = Firestore.instance
.collection(XXX)
.document(XXX)
.collection(XXX);
if (query['date'] == null) {
guestsRef
.where('lastName', isEqualTo: query['lastName'])
.where('firstName', isEqualTo: query['firstName'])
.getDocuments()
.then((doc) {
if (doc != null) {
result = doc.documents.map((x) => x.data).toList(); \\debugger shows this is working
}
}).catchError((e) => print("error fetching data: $e"));
}
return result;
and finally the problem:
FutureBuilder<List<Map>>(
future: results,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
List guests = snapshot.data;
return ListView.builder(
shrinkWrap: true,
itemCount: guests.length,
itemBuilder: (context, index) {
return ListTile(
... //do stuff here
);
},
);
} else {
return CircularProgressIndicator();
}
},
)
snapshot.data will indeed turn out to be a List, but the size is always 0 despite the getGuestData query finding users.

Resources