getting documents from another collection problem can't solve - flutter

i have these 2 collection with a users collection and i want to make a list of providers for one user
i tried this code but not give me results :(
Future<List<ServineraProvider>> getfavoritesForUser() async{
List<ServineraProvider> providers = [];
await providerSkillsCollection.where('providerID', isEqualTo: this.uid).get()
.then((onValue){
for(int i=0; i<onValue.docs.length; i++){
var doc = onValue.docs[i].data() as Map<String,dynamic>;
print(doc['skillID']);
skillsCollection.doc(doc['skillID']).get()
.then((doc){
var data = doc.data() as Map<String,dynamic>;
providers.add(ServineraProvider(
providerID: data['providerID'],
providerName: data['providerName'],
providerEmail: data['providerEmail'],
providerPhoneNumber: data['providerPhoneNumber'],
providerPicture: data['providerPicture'],
providerState: data['providerState'],
providerStatus: data['providerStatus']
)
);
});
}
});
return providers;
}
i know there is a mistake but can't solve

You're combining then with await, which is almost never a good idea. In this case it results in returning the providers list after the providerSkillsCollection query has completed, but before any of the providers themselves have been loaded.
To solve the problem with just await:
Future<List<ServineraProvider>> getfavoritesForUser() async{
List<ServineraProvider> providers = [];
var onValue = await providerSkillsCollection.where('providerID', isEqualTo: this.uid).get()
for(int i=0; i<onValue.docs.length; i++){
var doc = onValue.docs[i].data() as Map<String,dynamic>;
print(doc['skillID']);
var doc = await skillsCollection.doc(doc['skillID']).get()
var data = doc.data() as Map<String,dynamic>;
providers.add(ServineraProvider(
providerID: data['providerID'],
providerName: data['providerName'],
providerEmail: data['providerEmail'],
providerPhoneNumber: data['providerPhoneNumber'],
providerPicture: data['providerPicture'],
providerState: data['providerState'],
providerStatus: data['providerStatus']
));
}
return providers;
}

Related

How do I ensure that the list is populated before checking what it contains?

In the code snippet below, how do I ensure that the senderID list gets populated before checking what the list contains?
I'm pulling data from firestore, storing it in a list, and then checking if it contains a particular key.
Stream<List<Group>> getChatGroups(String grpId) {
return firestore.collection('groups').snapshots().map((event) {
List<Group> groups = [];
List<String> senderIds = [];
for (var document in event.docs) {
var group = Group.fromMap(document.data());
firestore.collection('groups').doc(group.groupId).collection('chats').get().then((QuerySnapshot snapshot) {
snapshot.docs.forEach((DocumentSnapshot doc) {
var messageData = doc.data() as Map<String, dynamic>;
var messages = Message.fromMap(messageData);
var grId = doc.reference.parent.parent?.id;
//The values in SenderIds should be set before the function below is initiaited
senderIds.add(messages.senderId);
});
});
//This if function should initiate after getting set above
if (senderIds.contains(auth.currentUser!.uid)) {
groups.add(group);
}
}
return groups;
});
}
If you want senderIds.contains to be called only after all of your Futures have completed, build a List of those Futures and use Future.wait on that List. Something like:
var futures = <Future<void>>[];
for (var document in event.docs) {
// ...
futures.add(
firestore
.collection('groups')
.doc(group.groupId)
.collection('chats')
.get()
.then((QuerySnapshot snapshot) {
// ...
}),
);
}
await Future.wait(futures);
if (senderIds.contains(auth.currentUser!.uid)) {
// ...
}
Note that since the above code is asynchronous, you should also be using asyncMap instead of map.

Flutter Populating List<String> using for loop

I want to get all the document IDs in my firebase and store it in List but I'm only getting one of the documents. Here is my execution
PrtSc
my code
Future saveUserCart(User currentUser) async
{
List<String> IDs = [];
Future getDocs() async {
QuerySnapshot querySnapshot = await FirebaseFirestore.instance
.collection('users')
.doc(currentUser.uid)
.collection("userCart").get();
for (int i = 0; i < querySnapshot.docs.length; i++) {
var itemIDs = querySnapshot.docs[i];
print(itemIDs.id);
IDs = [itemIDs.id];
}
print(IDs);
}
getDocs();
}
Fix my problem and learn something
Try IDs.add(itemIDs.id); instead of IDs=[itemIDs.id];
Instead of adding the code in question is creating a new list and assigning it to the last id. When we use add method we can get all ids from the documents.
Future saveUserCart(User currentUser) async
{
List<String> IDs = [];
Future getDocs() async {
QuerySnapshot querySnapshot = await FirebaseFirestore.instance
.collection('users')
.doc(currentUser.uid)
.collection("userCart").get();
for (int i = 0; i < querySnapshot.docs.length; i++) {
var itemIDs = querySnapshot.docs[i];
print(itemIDs.id);
IDs.add(itemIDs.id);
}
print(IDs);
}
getDocs();
}
It's just Example,
you can use base on your requirements. For gettings "ID" you don't need to use for loop, use "map" functions.
var data = [{'key':'abc', 'id':1},{ 'key': 'xyz', 'id': 2}];
var mapData = data.map((res) => res['id']);
print("mapData => ${mapData.toList()}");
Expected Output,
mapData => [1, 2]
Maybe, it will help you.

how to wait for a value and add it to list flutter

I have this piece of code
Future<List<RoomModel>> getTeacherRooms(String email) async {
var docs = await _roomRepo.getTeacherRooms(email);
List<RoomModel> rooms = [];
docs.map((doc) async {
var room = await toRoom(doc);
rooms.add(room);
}).toList();
return rooms;
}
I need to wait for toRoom() to return a value then put it in rooms
the problem is with this code is that rooms is returned empty
I just used "pskink" answer to solve this problem
this is the code
Future<List<RoomModel>> getTeacherRooms(String email) async {
var docs = await _roomRepo.getTeacherRooms(email);
return await Future.wait(docs.map((doc) => toRoom(doc)).toList());
}

How to Save List in SharedPreferences in Flutter

Hello all at first I want to mention that I've tried a lot of solutions here but it didn't work for me.
I bring the list from the database through the following code:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
}
return responsebody;
}else{
}
}
As is obvious in the code above I am trying to get the name and image and this is not a problem right now I want to store this listCat in SharedPreferences until I recall it from all pages of the app
I have the following class to save SharedPreferences:
class APIPreferences {
static SharedPreferences ? _preferences;
static const _keyMuinCat = 'MuinCat';
static Future init() async => _preferences = await SharedPreferences.getInstance();
static Future setMuinCat(String MuinCat) async => await _preferences!.setString(_keyMuinCat, MuinCat);
static String? getMuinCat() => _preferences!.getString(_keyMuinCat);
}
Then I save what I need to save by the following line:
APIPreferences.setMuinCat(listCat.toString());
Then I can bring pre-stored data from any location where I need it through the following code:
CatList = APIPreferences.getMuinCat() ?? '';
I tried to do the following thing now to save the list in the first code above:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
APIPreferences.setMuinCat(listCat.toString());
}
return responsebody;
}else{
}
}
But it didn't work. I don't really know how to deal with it.
How can I save it and then bring it to use with ListView.
instead of:
_preferences!.setString(_keyMuinCat, "some string");
use:
_preferences!.setStringList(_keyMuinCat, ["some", "strings", "in", "list"]);
So in your code, the setMuinCat method needs to be:
static Future setMuinCat(List<String> muinCat) async => await _preferences!.setStringList(_keyMuinCat, muinCat);
and then you call it like this:
APIPreferences.setMuinCat((listCat as List).map((v) => v.toString()).toList());
To save the list in shared preferences you need to pass as jsonEncode(yourList data) and when you will fecth the shared list you will again jsonDecode(your list)
await prefs.setString('YOUR KEY', json.encode(YOURMAP()));

How to retrieve one specific document from a collection on cloud firestore?

I need to retrieve a document from the 'announcements' collection of my document. Each of the documents in the collection is named a day of the year, for example '2020-07-02'. I want to retrieve the document for the current day. In the document, I need to access a map array titled 'details' containing the various announcements. How would I write that into my app? Here is what I am doing currently, but I don't know where to go from there.
Future getAnnouncements() async {
var currentDate = DateFormat("yyyy-MM-dd").format(DateTime.now());
var firestore = Firestore.instance;
Stream<DocumentSnapshot> qn = firerestore.collection('announcements').document(currentDate).snapshots();
return qn; //I want to only return the map array of the various documents
}
Try this
Future getAnnouncements() async {
var currentDate = DateFormat("yyyy-MM-dd").format(DateTime.now());
var firestore = Firestore.instance;
Future<DocumentSnapshot> qn = await firerestore.collection('announcements')
.document(currentDate)
.get();
return List<Map>.castFrom(qn["details"]);
}
To parse through the returned List, you could try this
List<Map> retrievedData = await getAnnouncements();
for(int i = 0; i < retrievedData.length; i++)
{
print(retrievedData[i]["title"]);
print(retrievedData[i]["text"]); // Thanks #VLXU
}