Error when trying to get data from Firestore - firebase

when I try to retrieve a data from firestore with this code.
Future<String> getUserType() async {
await (Firestore.instance
.collection('users')
.document(getUserUID().toString())
.get()
.then((DocumentSnapshot ds) {
return ds['type'];
}));
}
i get this error
NoSuchMethodError: The method '[]' was called on null.
I/flutter (15824): Receiver: null
I/flutter (15824): Tried calling: []("type")
I also tried:
return ds.data['type'];
The code to retrive the uid of user is:
Future<String> getUserUID() async {
return (await _firebaseAuth.currentUser()).uid;
}
but I don't think that this is the problem, maybe in ds there is nothing.

You need to retrieve the userID first and then use that in your document retrieval:
Future<String> getUserType() async {
String userID = (await _firebaseAuth.currentUser()).uid;
await (Firestore.instance
.collection('users')
.document(userID)
.get()
.then((DocumentSnapshot ds) {
return ds['type'];
}));
}
In your code:
Future<String> getUserUID() async {
return (await _firebaseAuth.currentUser()).uid;
}
getUserUID() returns a Future, but when you do .document(getUserUID().toString()) you are not getting the result of that Future.
Check the following:
https://dart.dev/codelabs/async-await

Your getUserUID() method returns a Future String not a regular String.So that you cannot directly get a document by providing that.This is the usual way I implement a function like this.
Future<String> getUserType() async {
getUserUID().then((currentUser) {
if (currentUser != null) {
await (Firestore.instance
.collection('users')
.document(currentUser)
.get()
.then((DocumentSnapshot ds) {
return ds['type'];
}));
}
}
}

Related

Firebase getting all docs from a collection

Hello I want to get all docs from a collection in one shot without knowing the docs id's since they are random. Inside each doc I have some data but all I need is the doc itself than I will take the data from each and every one no problem.
I get null every time.
Does anyone know what am I doing wrong?
Thank you in advance.
This is the code :
import 'package:cloud_firestore/cloud_firestore.dart';
Future<Map<String, dynamic>> getVisitedCountries(String ID) async {
Map<String, dynamic> val = <String, dynamic>{};
await FirebaseFirestore.instance
.collection('users')
.doc(ID)
.collection('PersonalData')
.doc(ID)
.collection('Passport')
.doc(ID)
.collection('VisitedCountries')
.doc()
.get()
.then((value) {
if (value.data().isEmpty) {
print("User not found");
} else {
val = value.data();
}
}).catchError((e) {
print(e);
});
return val;
}
This is the structure in the Cloud Firestore
So for everyone who is having this problem, this is the way to solve it.
I solved it thanks to the user : Kantine
Solution : code :
import 'package:cloud_firestore/cloud_firestore.dart';
Future<Iterable> getVisitedCountries(String ID) async {
// Get data from docs and convert map to List
QuerySnapshot querySnapshot = await FirebaseFirestore.instance
.collection('users')
.doc(ID)
.collection('PersonalData')
.doc(ID)
.collection('Passport')
.doc(ID)
.collection('VisitedCountries')
.get();
final val = querySnapshot.docs.map((doc) => doc.data());
return val;
}
I used a query snapshot to get the data and then mapped it.

How to get Firestore Data by method in Flutter

I am trying to get users name but Flutter gives this error:
The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.
Method:
String getUserNameFromUID(String uid) {
FirebaseFirestore.instance
.collection('users')
.where('uid', isEqualTo: uid)
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
return doc["name"];
});
});
}
How can I solve my problem? if I add return 0 to end of the method it always gives 0.
It always gives 0.(I do not want 0, I want get user name from uid)
String getUserNameFromUID(String uid) {
FirebaseFirestore.instance
.collection('users')
.where('uid', isEqualTo: uid)
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
return doc["name"];
});
});
return "0";
}
EDIT: I need a String solution, not Future. The method should return String...
Because my UI is not future builder. Isn't there any way to return one data as String in Firestore database?
First your function should return a Future<String> since it relies on firestore's get wich also returns a future. Also docs is a list, you have to return just one. The first one i guess. In the UI just use a FutureBuilder
Future<String> getUserNameFromUID(String uid) async {
final snapshot = await FirebaseFirestore.instance
.collection('users')
.where('uid', isEqualTo: uid)
.get();
return snapshot.docs.first['name'];
}
Since you can't use FutureBuilder. An ugly alternative is to pass a callback to getUserNameFromUID and call setState from there.
void getUserNameFromUID(String uid, Function (String name) onData) {
final snapshot = await FirebaseFirestore.instance
.collection('users')
.where('uid', isEqualTo: uid)
.get().then((s) => onData(s.docs.first['name']));
}
On your UI
...
getUserNameFromUID(uid, (String name){
setState(()=> name = name);
});
From your last comment just inherit from StatefulWidget. And call the function from inside.
#override
void initState() {
getUserNameFromUID(uid);
}
If you had special requirements about not being able to modify the UI, you should mention that as it conditions the way to use the backend services.

Comparing elements Flutter/FirebaseFirestore

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.

Flutter Firestore doc get returning null

I am trying to get a document from a Firestore collection using the following code:
firebase_service.dart:
class FirebaseService {
final firestoreInstance = FirebaseFirestore.instance;
final FirebaseAuth auth = FirebaseAuth.instance;
Map<String, dynamic> getProfile(String uid) {
firestoreInstance.collection("Artists").doc(uid).get().then((value) {
return (value.data());
});
}
}
home_view.dart:
Map<String, dynamic> profile =
firebaseService.getProfile(auth.currentUser.uid);
When stepping through the code the profile variable is null in home_view.dart, but value.data() in firebase_service.dart contains a map. Is there a reason why this value isn't being returned in home_view.dart?
Your code needs a few edits, as the getProfile function is async.
class FirebaseService {
final firestoreInstance = FirebaseFirestore.instance;
final FirebaseAuth auth = FirebaseAuth.instance;
// set the return type to Future<Map<String, dynamic>>
Future<Map<String, dynamic>> getProfile(String uid) async { // insert async here
/// insert a return and await here
return await firestoreInstance.collection("Artists").doc(uid).get().then((value) =>
return value.data(); // the brackets here aren't needed, so you can remove them
});
}
}
Then finally in home_view.dart
// insert await here:
Map<String, dynamic> profile = await
firebaseService.getProfile(auth.currentUser.uid);
If you plan to use the getProfile function I suggest you to use a FutureBuilder.
In you home_view.dart's build function write this:
return FutureBuilder(
future: firebaseService.getProfile(auth.currentUser.uid),
builder: (context, snapshot){
if (!snapshot.hasData){
return Center(child: CircularProgressIndicator(),);
}
final Map<String, dynamic> profile = snapshot.data.data();
return YourWidgets();
});
And now you don't need to write:
Map<String, dynamic> profile = await
firebaseService.getProfile(auth.currentUser.uid);
This is an async operation and you have to await for its value.
For reference, you can take a look here at documentation of how propper authentication and CRUD operations made in Firebase with flutter.

How can I check this in collection?

I have added this collection:
Map<String, String> userDataMap = {
"userName": usernameEditingController.text,
"userEmail": emailEditingController.text,
"account": userType // there is premium and regular account type
};
...
Future<void> addUserInfo(userData) async {
Firestore.instance.collection("users").add(userData).catchError((e) {
print(e.toString());
});
}
And actually I don't know how to get info about account type, I would like to print/get value assigned to "account".
This is what I tried but it did nothing:
var ok = await Firestore.instance
.collection('users')
.where('email', isEqualTo: email)
.getDocuments();
print(ok);
Thank you in advance.
Inside the document, you have a field called userEmail and not email therefore you need to do the following:
var userDoc = await Firestore.instance
.collection('users')
.where('userEmail', isEqualTo: email)
.getDocuments();
userDoc.documents.forEach((result) {
print(result.data["account"]);
});

Resources