RangeError (RangeError (index): Invalid value: Valid value range is empty: 0) with Cloud Firestore - flutter

I know this question has been asked alot but this is very different, I am querying my firestore database to return users that a person searches. Then it returns the data of the specific person you are searching for.
here is the code
await firestore
.collection('users')
.where("email", isEqualTo: _search.text)
.get()
.then((value) {
setState(() {
userMap = value.docs[0].data();
isLoading = false;
});
});
The problem is whenever I input a value in the search bar that is NOT a user on the database, it gives me that error "RangeError (RangeError (index): Invalid value: Valid value range is empty: 0)". I understand it's because the thing being searched for doesn't exist yet but I have no idea how to fix it, please help!

You need to add a check with if statement that the length of value.docs is not equal to zero.
.then((value) {
if(value.docs.length.isNotEmpty){
setState(() {
userMap = value.docs[0].data();
isLoading = false;
});
}

Write an if statement in the .then fallback function to see if value.docs.length is greater then 0 and if yes, use the code you have, and if not (in the else) it doesn't exist and write what it should do in that situation.

Related

Order by clause cannot contain a field with an equality filter email

I want to read the text of a textfield (with the controller emailController) and find out, if the email exists in my collection "admins".
If the email exists in my collection, then it should return true. Otherwise it should return false.
At first I created the firebase request and then I get the result of the query.
If the query is not null, then it should return true. Otherwise it should return false. (when it is null, then there is no email in the collection which is equal to the emailController)
When I run the code I am getting an error:
Error: [cloud_firestore/invalid-argument] Order by clause cannot contain a field with an equality filter email
at Object.createErrorWithStack (http://localhost:60283/dart_sdk.js:5660:12)
at Error._throw (http://localhost:60283/dart_sdk.js:21577:18)
at Error.throwWithStackTrace (http://localhost:60283/dart_sdk.js:21571:18)
at async._AsyncCallbackEntry.new.callback (http://localhost:60283/dart_sdk.js:43533:18)
at Object._microtaskLoop (http://localhost:60283/dart_sdk.js:43360:13)
at _startMicrotaskLoop (http://localhost:60283/dart_sdk.js:43366:13)
at http://localhost:60283/dart_sdk.js:38600:9
code:
Future <bool> getAdminExistance()async{
var i =
await FirebaseFirestore.instance.
collection('admins').
orderBy('email').
where('email', isEqualTo: emailController.text.trim());
QuerySnapshot querySnapshot = await i.get();
if(querySnapshot == null){
return false;
}
else{
return true;
}
}
already tried this without orderby and this too:
Future <bool> getAdminExistance()async{
var i =
await FirebaseFirestore.instance.
collection('admins')
.where('email', isEqualTo: email.text.trim())
.get()
.then((value) => value.size > 0 ? true : false);
}
But it won't work either.
You cannot order your query by any field included in an equality (=) or in clause.
See Limitations for details.

Flutter if statement not functioning

This should be an easy one but I've been stuck for hours.
Situation: I'm trying to execute the signOutProcess to log out of Firebase if the user is not authorized. I've set up a field in Firestore, 1 for authorized and 0 for not authorized. It prints the correct result, I can get it to sign out if I remove the if statement but that defeats the purpose.
Question: How do I get the if statement to execute signOutProcess when the nested value is retrieved?
void getUserAuthorization () {
String uid = firebaseAuth.currentUser!.uid;
print('this is uid $uid');
FirebaseFirestore.instance
.collection('Users2022')
.doc(uid)
.get()
.then((DocumentSnapshot documentSnapshot) async {
dynamic nested = documentSnapshot.get(FieldPath(['Authorized']));
print('this is the authorization condition $nested');
if (nested == 0) {
signOutProcess();
}
});
}
Likely the value you get is '0' and not 0, i.e. it's a string!
It won't be equal to the number 0 then, and instead you'd have to write if (nested == '0').
You can try print(nested.runtimeType) to see what you actually got there.

How to add Firestore data into List<List>

I want to add Firestore data into List to display it in a pdf report, this way wouldn't work properly I mean they not show the data in the list and display some error I don't know what the problem?
Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform"
theData() async {
await FirebaseFirestore.instance
.collection('QFS')
.snapshots()
.forEach((QuerySnapshot snapshot) {
for (int index = 0; index < snapshot.docs.length; index++) {
List<List> listOfData = [];
listOfData
.add({snapshot.docs[index]["commodity"]}.toList());
print(listOfData);
}
});
}
I think you should try optimising your code using forEach() loop instead of for() loop and you should try using docs[index].get(‘commodity’) instead of docs[index][“commodity”].
You can refer to these stackoverflow links for more insight: Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform, How to fix Bad state: field does not exist within the DocumentSnapshotPlatform.

How to update nested field inside a document in Firestore Flutter

I am working with Flutter and Cloud Firestore, and I'm stuck on the point where I need to update a nested field inside my collection -> document. Below is the screenshot of my firestore collection structure. I know how to do basic update method like FirebaseFirestore.instance.collection('collection_path').doc('data').update(...), however, in my case, the document structure is a bit complex so I need some help in case of performing update method.
Here, I need to change (on a button press) the field status to true/false under strategies array.
I have the access to strategyName field so that I could get that item in the strategies array and change it...
What I tried:
ElevatedButton(
onPressed: () async {
// status=true
final value = await FirebaseFirestore.instance
.collection(widget.symbol + '_Live')
.doc("data")
.get();
final data = value.data();
final strategies =
data!['strategies'] as List<Map<String, dynamic>>;
final strategy = strategies.firstWhere(
(item) => item['strategyName'] == strategyName,
orElse: () => Map());
strategy['status'] = true;
await FirebaseFirestore.instance
.collection(widget.symbol + '_Live')
.doc("data")
.update(data);
},
child: Text("Start"),
),
Obviously, this won't work because here I'm just changing it locally, i.e. not using the Firestore update method to actually change the field. But I'm confused as to how to update that nested field.
Any leads/help would be really appreciated!
EDIT:
I did as you told and edited my answer, but now the error is gone but nothing seems to work, i.e. in firestore, there is no change in the data doc.
ERROR: Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>' in type cast
You need to update value map locally, then store it back:
final value = await FirebaseFirestore.instance
.collection(symbol + '_Live')
.doc("data")
.get();
final data = value.data();
final strategies =
data!['strategies'].map((item) => item as Map<String, dynamic>).toList();
final strategy = strategies.firstWhere(
(item) => item['strategyName'] == strategyName,
orElse: () => Map());
strategy['status'] = toggleValue;
await FirebaseFirestore.instance
.collection(symbol + '_Live')
.doc("data")
.update(data);
The point is to store the entire value.
EDIT by Author : Just needed to map each element to Map<String, dynamic>.

FLUTTER FIRESTORE -Query the field and get document id and check other field

am trying to get the searched value(userid) which is in the field of a document in firestore I want to check the other fields(status) of the document I tried this method but failed
handlesubmit(BuildContext context)async{
final QuerySnapshot searcheduserid=
await Firestore.instance.collection('users')
.where('userid',isEqualTo: userid).limit(1).getDocuments();
final userdocid=searcheduserid.documents.map((doc)=>doc.documentID);
final DocumentSnapshot getuserdoc= await Firestore.instance.collection('users')
.document(userdocid).get();
final userstatus = getuserdoc.data['status'];
// I GET AN ERROR HERE ERROR SAYS
// METHOD [](status) was called on null
if(userstatus==null){
return showdialog( context,'the entered user id status does not exist');
}
}
You probably copied an older version of your code because it is unlikely that your code compiles the following line of your program:
final DocumentSnapshot getuserdoc= await Firestore
.instance
.collection('users')
.document(userdocid).get();
The error message on my system is:
The argument type 'Iterable<String>' can't be assigned to the parameter type 'String'.
Which means that userdocid is an Iterable of type String (Iterable<String>), but a parameter which is of type String is expected.
You have multiple options of fixing the problem, but I suggest the following:
Since you are only expecting one document from your QuerySnapshot it is enough to just look at the first document.
final QuerySnapshot searchedUserId = await Firestore.instance
.collection('users')
.where('userid', isEqualTo: userid)
.limit(1)
.getDocuments();
// if it is possible that searchedUserId returns no document make sure to
// check whether searchedUserId.documents.length > 0,
// otherwise searchedUserId.documents.first will throw an error
DocumentSnapshot document = searchedUserId.documents.first;
final userDocId = document.documentID;
final DocumentSnapshot getuserdoc =
await Firestore.instance.collection('users').document(userDocId).get();
Improved Solution:
However I think your code is a bit redundant anyways, because you are looking up a field of a document which has the same value as the document ID. You could shorten the whole code to
final DocumentSnapshot getuserdoc =
await Firestore.instance.collection('users').document(userid).get();
Error calling getuserdoc.data['status']
If you get an error saying something similar to
[](status) was called on null
Then that means getuserdoc has no value. This is likely due to the fact that there is no such database entry with the given ID. Check if the ID is in your database, otherwise comment below for additional information, because the provided code had compilation errors and does not run at all.