In the example below, I want to combine 2 firestore queries, but I could not get it to work.
final List<Who> pagedData =
await _query.get().then((QuerySnapshot snapshot) async {
if (snapshot.docs.isNotEmpty) {
_lastDocument = snapshot.docs.last;
} else {
_lastDocument = null;
}
return snapshot.docs.map((QueryDocumentSnapshot e) async {
final data = e.data() as Map<String, dynamic>;
Whoes w = Whoes.fromMap(e.data());
User u = await _firestore
.collection("user")
.doc(data['s'])
.get()
.then((DocumentSnapshot documentSnapshot) => User.fromMap(
documentSnapshot.data()));
return Who(w, u);
}).toList();
});
When I put await in the user part, things get confused and I couldn't edit it.
What I want to output as a result is List<Who>
What am I missing?
It gives me this error:
The return type 'List<Future<Who>>' isn't a 'Future<List<Who>>', as required by the closure's context.
I solved the problem, I leave it here for anyone who encounters this
final List<Who> pagedData =
await _query.get().then((QuerySnapshot snapshot) async {
if (snapshot.docs.isNotEmpty) {
_lastDocument = snapshot.docs.last;
} else {
_lastDocument = null;
}
Iterable<Future<Who>> futureWho =
snapshot.docs.map((QueryDocumentSnapshot e) async {
final data = e.data() as Map<String, dynamic>;
Whoes w = Whoes.fromMap(e.data());
User u = await _firestore
.collection("user")
.doc(data['s'])
.get()
.then((DocumentSnapshot documentSnapshot) => User.fromMap(
documentSnapshot.data()));
return Who(w, u);
});
Future<List<Who>> listWho = Future.wait(futureWho);
return listWho;
});
Related
this is my first question.
Right now my code is working when adding 'displayName' to List:
final usersRef = FirebaseFirestore.instance.collection('users');
List userList = [];
void getUsers() async {
List<String> newUserList = [];
await usersRef.get().then((QuerySnapshot snapshot) {
snapshot.docs.forEach((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data = documentSnapshot.data();
newUserList.add(data['displayName']);
});
});
setState(() {
userList = newUserList;
});
}
But I want to add 'userList[id]' AND 'userList[displayName]' to list the 'displayName' in DropDown BUT to send(push) the 'id':
DropdownSearch<String>(
...
items: userList,
...
onChanged: (String value) {
Navigator.push(context,MaterialPageRoute(builder: (context) => ProfilePage(profileId: value),
...
Because in DropDown-List Names could be duplicate like John Doe but a List of unique IDs to select makes no sense ... Any help?
The await in await usersRef.get()... is not doing anything, since you're not returning anything from within the callback.
I highly recommend using either async/await or then, but not both.
With then the code would be:
void getUsers() {
List<String> newUserList = [];
usersRef.get().then((QuerySnapshot snapshot) {
snapshot.docs.forEach((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data = documentSnapshot.data();
newUserList.add(data['displayName']);
});
setState(() {
userList = newUserList;
});
});
}
And with async/await it'd be:
void getUsers() async {
List<String> newUserList = [];
QuerySnapshot snapshot = await usersRef.get();
snapshot.docs.forEach((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data = documentSnapshot.data();
newUserList.add(data['displayName']);
});
setState(() {
userList = newUserList;
});
}
i have a problem with getting users, whose emails are in the other user's array 'SeniorList'. It prints me empty array when i have a user with an email from
_seniorList
I'm new to a Firebase so every advice is important.
Here is Firestore DB structure:
https://imgur.com/yrtJ4RZ
https://imgur.com/z3gurUq
And Code i tried:
Future<List<String>> getSeniorList() async {
var _currentUser = FirebaseAuth.instance.currentUser;
List<String> list;
DocumentSnapshot data = await FirebaseFirestore.instance
.collection('users')
.doc(_currentUser!.uid)
.get();
list = List.from(data['SeniorList']);
return list;
}
Future<void> printSeniorNameList() async {
final List<String> _seniorList = await getSeniorList();
print(_seniorList);
final QuerySnapshot result = await FirebaseFirestore.instance
.collection('users')
.where('email', arrayContainsAny: _seniorList)
.get();
final List<DocumentSnapshot> documents = result.docs;
print(documents);
}
PS. If u can tell me how to paste Images in a right way i will be thanksfull!
Solved it this way:
Future<List<String>> getSeniorList() async {
var _currentUser = FirebaseAuth.instance.currentUser;
List<String> list;
DocumentSnapshot data = await FirebaseFirestore.instance
.collection('users')
.doc(_currentUser!.uid)
.get();
list = List.from(data['SeniorList']);
return list;
}
Future<bool> isSeniorAlreadyInTheList(String checkemail) async {
final List<String> _seniorList = await getSeniorList();
if (_seniorList.contains(checkemail)) {
return true;
} else {
print('Email not in a Senior List');
return false;
}
}
Future<void> printSeniorNameWhoseEmailInTheList(String checkemail) async {
bool exists = await isSeniorAlreadyInTheList(checkemail);
Map<String, dynamic>? seniorName;
if (exists) {
var result = await FirebaseFirestore.instance
.collection('users')
.where('email', isEqualTo: checkemail)
.limit(1)
.get();
seniorName = result.docs[0].data();
print(seniorName!['username']);
} else
print('That users email is not in a SeniorList!');
}
Already Works for me.
Upon creating an account the user's firestore creates a field that displays the current amount of plastics the user has. So far, I have a button that updates that amount using the user's text field input. I've heard of something called a transaction which apparently allows one to intsead add the input amount to the overall data for it to be displayed? How would I accomplish this in my case when the use inputs a new amount?
Code:
database.dart
Future<void> userSetup(String displayName) async {
int plastics = 0;
final CollectionReference users =
FirebaseFirestore.instance.collection('UserNames');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser.uid.toString();
users.doc(uid).set({'displayName': displayName, 'uid': uid});
//This is the field for plastics amount starting at 0.
users.doc(uid).update({'plastics': plastics});
return;
}
How I retrieve the amount data:
final firestore = FirebaseFirestore.instance;
FirebaseAuth auth = FirebaseAuth.instance;
Future<String> getPlasticNum() async {
final CollectionReference users = firestore.collection('UserNames');
final String uid = auth.currentUser.uid;
final result = await users.doc(uid).get();
return result.data()['plastics'].toString();
}
How I display it:
FutureBuilder(
future: getPlasticNum(),
builder: (_, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
return Text(snapshot.data,
style: TextStyle(color: Colors.amber[400], fontSize: 20));
},
),
Currently how the user can replace the amount, but not add to it(The problem)
OnPressed: () async {
try {
final String uid = auth.currentUser.uid;
FirebaseFirestore.instance
.collection('UserNames')
.doc(uid)
.update({
"plastics": int.parse(_plasticController.text),
});
Navigator.of(context).pop();
} catch (e) {}
},
I made a separate future to take care of adding:
final firestore = FirebaseFirestore.instance; //
FirebaseAuth auth = FirebaseAuth.instance;
Future<bool> addPlastic(String amount) async {
try {
String uid = auth.currentUser.uid;
var value = double.parse(amount);
DocumentReference documentReference =
FirebaseFirestore.instance.collection('UserNames').doc(uid);
FirebaseFirestore.instance.runTransaction((transaction) async {
DocumentSnapshot snapshot = await transaction.get(documentReference);
if (!snapshot.exists) {
documentReference.set({'plastics': value});
return true;
}
double newAmount = snapshot.data()['plastics'] + value;
transaction.update(documentReference, {'plastics': newAmount});
return true;
});
} catch (e) {
return false;
}
}
Then I just called it when the button was pressed
onPressed(){
addPlastics(_plasticController.text);
}
Trying to capture a specific field from my documents. Here is the code for the wrapper,
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print(user);
// return either the Home or Authenticate widget
if (user == null) {
return Authenticate();
} else {
return FirmHomePage();
}
}
}
and this is the code that we used for printing in the console.
void idss() async {
FirebaseUser userid = await FirebaseAuth.instance.currentUser();
var document = await Firestore.instance.collection('Users').getDocuments();
for (var document in document.documents) {
messagetext = document.data['JobType'];
usettype = messagetext;
print(messagetext);
}
}
We want to check our user to set a path for them.
FirebaseUser userid = await FirebaseAuth.instance.currentUser();
final QuerySnapshot result = await Firestore.instance.collection('Users')
.where('uid', isEqualTo: currentUser.uid) .getDocuments();
final List < DocumentSnapshot > documents = result.documents;
if (documents.length == 1) {
//your code here
}else{
//your code here
}
I am trying to implement the function below but it gives me null.
To be specific, Future credit() is not updating the variable value. There is no problem with the database because if I put print(doc['value']) instead of value += doc['value'], I get the expected result.
It seems, getCredit() is the one returning null.
Future credit() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
final String uid = user.uid;
int value = 0;
Firestore.instance
.collection('entries')
.where("uid", isEqualTo: uid)
.where("type", isEqualTo: "+")
.orderBy("time", descending: true)
.snapshots()
.listen((data) => data.documents.forEach((doc) => value += doc['value']));
print(value); // doesnt update value
return value;
}
int getCredit() {
credit().then((value) {print(value);});
credit().then((value) {return value;}); // return mot working
}
Thanks!
try this:
Future<int> getCredit() async {
return await credit();
}
Fixed it. It seems it was a problem with the scope of variable.
int cr = 0;
Future credit() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
final String uid = user.uid;
Firestore.instance
.collection('entries')
.where("uid", isEqualTo: uid)
.where("type", isEqualTo: "+")
.orderBy("time", descending: true)
.snapshots()
.listen((data) => data.documents.forEach((doc) {cr = cr + doc['value'];}));
print('$cr');
}