Getting all documents uids from firestore and add them to a list .flutter - flutter

I created a new collection named users on my firestore project. Im trying to get a list of all auto generated id's in that collection. So far I tried
late List<String> userID = [];
Future getID() async {
await FirebaseFirestore.instance.collection('users').get().then(
(snapshot) => snapshot.docs.forEach((document) {
userID.add(document.reference.id);
}),
);
}
But whenever I try to access the Strings of id's in the list , it returns an empty list

getID is a future method. It will take some to fetch data. After getting data you need to call setState to update the UI. You dont need to await and .then same time
try
Future getID() async {
FirebaseFirestore.instance.collection('users').get().then((snapshot) {
snapshot.docs.forEach((document) {
userID.add(document.reference.id);
});
setState(() {});
});
}
It would be great to use FutureBuilder for future method.

Related

Flutter firestore update subcollection

I have a collection recipes with a subcollection notes.
How can I update a note? I can't find a way to get the right document id to make the update function.
I'm passing the document to a card widget with Get.arguments and there I have a button to update the note.
The button code:
onTap: () async {
await _updateNotes(
_notesController.text,
documentSnapshot.reference.id,
);
}),
The method code:
Future<void> _updateBrewNotes(String brewNotes) async {
await Globals.updateNotes(brewNotes, documentSnapshot.reference.id,
documentSnapshot.reference.id);
Get.to(() => const HomePage());
}
That calls other file named Globals with the code:
static updateNotes(startNotes, String idRecipe, String idNotes) {
recipes
.doc(idRecipe)
.collection('notes')
.doc(idNotes)
.update({'notesStart': startNotes});
}
That recipes is a simple collection to shorten the code
static final CollectionReference recipes =
FirebaseFirestore.instance.collection('recipe');

How to return a List, after a Method fills it, Flutter

I'm stuck with a problem and I wondered if you can help me.
I have a functions (in Flutter) that returns a List of Items. Now this List of Items should be Filled by an other function, which goes thought my Database and collect the right items. My Problem is, that my Function runs after the Return Statement... Here is some Code:
Future<List<MaterialItem>> getItems(String path, String fach) async {
// This is a empty List that I want to fill
List<MaterialItem> list = [];
// That's my Function, that fills the List
var result = await _db
.collection("$path/$fach/")
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
// Here the List gets filled
list.add(MaterialItem.fromSnapshot(doc.data() as Map<String, dynamic>));
});
});
// Here the List should be returned, but after my Function fills it.
return list;
}
Hope you know what my problem is, and someone can help me.
I think you could solve this using a Completer. Your function should return the Future property of the Completer and the database call should then complete it.
Take a look at the API and the example:
https://api.dart.dev/stable/2.12.4/dart-async/Completer-class.html
For example: (pseudo code)
Future<List<MaterialItem>> getItems(String path, String fach) async {
// declare a completer
Completer<List<MaterialItem>> completer = Completer();
List<MaterialItem> list = [];
final result = await _db
.collection("$path/$fach/")
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
list.add(MaterialItem.fromSnapshot(doc.data() as Map<String, dynamic>));
});
// let the database call complete the completer
completer.complete(list);
});
// return the future value of the completer
return completer.future;
}

How to convert Future List instance to List String in flutter

I am saving strings list in shared procedure and fetching that like below
Future<List<String>> getList() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getStringList("key");
}
Issue is that I need to send that list to server but facing issue as I need to convert that future list to simple List
How can I do that? or is there any other way as I need to send list of ids save by user to server.
When you mark a function as async it will return a future.
If you dont wait for the future you will get 'Future instance' this means your future(data) is not available yet.
If you want to wait for the future(data) to be resolved you need to use the await keyword.
So in your case you can create a List<String> myList; then create a function to wait for the future and assign the data to the previous List.
List<String> myList;
void getStringList() async {
var tempList = await getList();
// Or use setState to assign the tempList to myList
myList = tempList;
}
Or use Then:
getList().then(List<String> myList {
// TODO: Send myList to server.
});
Hope this helpe!!
When you work with async data you should "wait" while data will not completely loaded. You can use await word in async methods like that:
foo() async {
final Future<List<dynamic>> futureList = fetchSomeFutureList();
final list = await futureList;
}
or use Future's then() method to delegate some work.
You also can wait for futures in widget tree using FutureBuilder.
Check Dart Docs page for see details.

FIrestore Query Document in Collection Using Single Field/Attribute in Flutter

I am trying to fetch the role of the currently authenticated user stored in users collection. What I am trying to achieve is at login time, query the user role by traversing fetching the user's document in the collection and sifting through the fields or checking all documents and returning the field role as a string.
Collection and document snapshot(excuse the terminology):
All documents in users collection have same fields for now.
Please how do I go about writing this type of query in flutter? I have tried using AuthResult in my service and FirebaseAuth to get current user(but no way to access the fields in the document).
Thanks.
String role;
getUserRoleWithFuture() async {
String currID = await _authService.getCurrentUID();
String mRole;
Firestore.instance.collection(USERS_REF).document(currID).get().then((doc) {
mRole = doc.data['role'];
print(mRole);
});
return mRole;
}
Future<String> getUserRoleWithStream() async {
String currID = await _authService.getCurrentUID();
String sRole;
Firestore.instance
.collection(USERS_REF)
.document(currID)
.snapshots()
.listen((DocumentSnapshot ds) {
if (ds.exists) {
sRole = ds.data['role'];
print('with stream:\t$sRole');
}
});
return sRole;
}
In the method getUserRoleWithStream() I am trying to retrieve the value printed out like role = getUserRoleWithStream() but instead get this in console a value of type Future<String> can't be assigned to a variable of type string.
How do I get this value using either the stream (cos it constantly observes the collection) or using the other method and use it in my widget?
Thanks again.
This is the working solution, in case anyone else runs into this. I appreciate the effort made into helping me understand the issue but here's the answer:
String role;
getUserRoleWithFuture() async {
String currID = await _authService.getCurrentUID();
String mRole;
Firestore.instance.collection(USERS_REF).document(currID).get().then((doc) {
mRole = doc.data['role'];
print(mRole);
});
return mRole;
}
Future<String> getUserRoleWithStream() async {
String currID = await _authService.getCurrentUID();
String sRole;
Firestore.instance
.collection(USERS_REF)
.document(currID)
.snapshots()
.listen((DocumentSnapshot ds) {
if (ds.exists) {
sRole = ds.data['role'];
print('with stream:\t$sRole');
}
});
return sRole;
}
Well first off, I assume the AuthResult.user.uid and your user's collection user's id is same. So that once you have the user from AuthResult, you can query your firestore collection to get the user's role as follows.
Future<String> getUserRole(String uid) async {
DocumentSnapshot ds = await Firestore.instance.collection('users').document(uid).get();
return ds.data['role'];
}

How to upload contacts as Iterable from Flutter to Firestore

I'm creating an app which will upload all contacts to Firestore database with map type. But below code do not upload contacts to Firestore. Please help.
I have been trying to fetch contacts from my phone to Firestore using Flutter app. I used contact_services library to fetch contacts. Even after trying some similar examples, I could not my contacts to Firestore using map type. Where do I make changes so that I can upload all my contacts as map value to Firestore
final Iterable<Contact> contacts = await ContactsService.getContacts(withThumbnails: false);
Firestore.instance
.collection('contacts')
.document(firebaseUser.uid)
.setData({
'contact':{ contacts.map((Contact contact){ 'name': contacts.displayName,contacts.phone})}
});
I expected to display all my contacts in firestore with map type, but actual output is none were uploaded.
I am sure you have fixed this since this is an old post. But there are a few things incorrect with how you are using the map method id Dart.
You named your element variable "contact" and not "contacts" so that is the variable you should be referencing "contact" to get your information. So it would be contact.displayName.
You are not returning anything. Because there is no "=>" there is no implicit return and because there is no "return" there is no explicit return.
Also, what you are returning from the map method is an Iterable to the contact field.
I am not sure what you are trying to accomplish here. Are you trying to insert a nested object? If so, your phone is also missing a key
Little late but, this is for the reference for the Firestore version ^0.16.0.
// your list of contacts in _contacts.
List<Contact> _contacts = [];
final FirebaseFirestore _db = FirebaseFirestore.instance;
CollectionReference _ref = _db.collection(collectionName);
Future<void> syncContacts({uid}) async {
try {
Map<String, dynamic> _data;
if (_contacts != null)
_data = {
'contacts': _contacts
.map((k) => {
'name ': k.displayName,
'phone': k.phones.first.value
.toString()
.replaceAll(new RegExp(r"\s\b|\b\s"), "")
.replaceAll(new RegExp(r'[^\w\s]+'), '')
})
.toList(),
};
log(_data.toString());
await _service.reference().doc(uid).set(_data, SetOptions(merge: true));
} catch (e) {
log(e.toString());
} finally {
notifyListeners();
}
}
P.S I have used flutter_contact library to get contacts from the device.