Is there a way to check the value of a specific field in a document? - flutter

I'm trying to compare the text inputted by user to my firestore collection.
But when I tried this code:
docSnapshot.data()!.containsValue(currentStudPass);
where currentStudPass is a String that contains the User ID which is 184-0055
It works but it's trying to search for all the fields value that the user has,
for example I tried "Test Section" as a password, it will return true.
I want to exclude all fields except the password: or just use containsValue for password: field. But I don't have any idea how to do that I'm new to Flutter.
I tried:
docSnapshot.data()!.containsValue('password: $currentStudPass');
var docSnapshot = await collection.doc("$currentStudId/password").get();
But it doesn't work.
Here's my firestore db.
static Future<bool> checkPass(String passArg) async {
// method to check if the users password is correct
var collection = FirebaseFirestore.instance.collection('users');
var docSnapshot = await collection.doc("$currentStudId").get();
try {
passCheck =
docSnapshot.data()!.containsValue(currentStudPass);
return passCheck;
} catch (e) {
// If any error
return false;
}

try this if this works.
static Future<bool> checkPass({String? id, String? passArg}) async {
final collection = FirebaseFirestore.instance.collection('users');
final docs = await collection.doc(id!).get();
final Map<String,dynamic> map = docs.data() as Map<String,dynamic>;
// you can direct it since the result from contains is bool
return map['password'].toString().contains(passArg!);
// Edit : you can use operator == to know exact input
// return map['password'] == passArg!;
}

Related

How to fetch data and update it from firebase

I am having trouble trying to fetch data from firebase and updating the values from it.
I have a restaurant name and the number of times it has been picked (user chooses to go to that restaurant to eat). I am trying to retrieve the numPicked and update it by adding one if the user decides to go there again.
Here i am trying to fetch ONE specific document and trying to store the docID and the variables I need to update.
docID = doc.id; docID is return NULL
meaning that the foreach loop isn't even being read.
Future<bool> searchQuery(
{required String restaurantName,
required var userID,
required db}) async {
int addOne = 1; //addes one if it has been picked
//this is not working
try {
Query query2 =
db.where('userId', isEqualTo: FirebaseAuth.instance.currentUser!.uid);
Query query = query2.where('restaurantName', isEqualTo: restaurantName);
await query.get().then((querySnapshot) {
// ignore: avoid_function_literals_in_foreach_calls
querySnapshot.docs.forEach((doc) {
docID = doc.id;
numPicked = doc['numPicked'];
restaurantExist = true;
});
}).catchError((error) {
// print('error querying: #error');
});
} catch (ex) {
// ignore: avoid_print
print(ex);
}
//this is not working
int totalPicked = numPicked + addOne;
//if the restaurant exist then update the numpicked for that specific restaurant
if (restaurantExist) {
try {
var query = db
//.collection('NumRestaurantPicked')
.doc(docID);
await query.update({'numPicked': totalPicked.toString()});
} catch (ex) {}
}
return restaurantExist;
}
The docID and numPicked variables are not defined in the method signature, so they are not accessible outside of the try block. They should be defined as class variables, so they can be accessed from other methods.

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());
}

Getting document from Firestore to pun inside a Custom User profile but it returns null. Dart/Flutter

Hi there I'm having some trouble to retrieve data from Firestore;
I created a class User for getting all the information for my app.
User Class:
class User {
String id;
String displayName;
String email;
String pictureURL;
String gender;
DateTime dateOfBirth;
User(fbauth.User user) {
id = user.uid;
displayName = user.displayName;
email = user.email;
pictureURL = user.photoURL;
// setting info
DocumentSnapshot resl = FirestoreUtil.read("AdditionalUserInfo", user.uid);
gender = resl.data()['gender'];
dateOfBirth = (resl.data()['date of birth'] as Timestamp).toDate();
}
FirestoreUtils class:
class FirestoreUtil {
static DocumentSnapshot read(String collection, String document) {
FirebaseFirestore.instance
.collection(collection)
.doc(document)
.get()
.then((DocumentSnapshot snapshot) {
if(snapshot.exists){
return snapshot;
}else{
print("no data found");
}
});
}
}
After I return the snapshot, it gets null. But if I do this it prints out the correct values:
class FirestoreUtil {
static DocumentSnapshot read(String collection, String document) {
FirebaseFirestore.instance
.collection(collection)
.doc(document)
.get()
.then((DocumentSnapshot snapshot) {
if(snapshot.exists){
print(snapshot.data);
}else{
print("no data found");
}
});
}
}
I tried literally everything but I couldn't figure out. Could someone help? I cannot imagine that is that hard to retrieve data inside a class.
It's probably Future(async/await) problem. You are returning value inside Future, you can get this value inside another then() etc.
class FirestoreUtil {
static DocumentSnapshot read(String collection, String document) async {
// You can directly return it too without assigning it to result variable
var result = await FirebaseFirestore.instance
.collection(collection)
.doc(document)
.get();
return result;
}
}
There is data() method for DocumentSnapshot, you can use result.data() and check if it's null, isEmpty etc.
I wrote this function with async/await but if you need Future and didn't want to wait operation to be finished, you can directly return
FirebaseFirestore.instance.collection(collection).doc(document).get();
and you can use then() after you get the Future.

How do I return to the user stream in flutter

I'm having an issue return a Stream to a StreamBuilder widget in a flutter. I'm trying to access a custom class that is stored token.
class User {
String token;
User({this.token});
}
===============================
class AuthService {
String url = 'https://reqres.in/api/login';
String token = '';
// {
// "email": "eve.holt#reqres.in",
// "password": "cityslicka"
// }
Map data;
Future signIn(String email, String password) async {
final response =
await post(url, body: {'email': email, 'password': password});
data = jsonDecode(response.body);
print(data['token']);
token = data['token'];
_userFromDatabaseUser(data);
return data;
}
//create user obj based on the database user
User _userFromDatabaseUser(Map user) {
return user != null ? User(token: user['token']) : null;
}
//user stream for provider
Stream<User> get user {
return .................. ;
}
You could use a stream controller:
class AuthService {
final String url = 'https://reqres.in/api/login';
final controller = StreamController<User>();
Future<User> signIn(String email, String password) async {
final response = await post(url, body: {'email': email, 'password': password});
final data = jsonDecode(response.body);
final user = _userFromDatabaseUser(data);
controller.add(user);
return user;
}
//create user obj based on the database user
User _userFromDatabaseUser(Map user) {
return user != null ? User(token: user['token']) : null;
}
//user stream for provider
Stream<User> get user {
return controller.stream;
}
Please note that this approach is a simplistic example that has some flaws, you should read up on it in the documentation.
If you use this for the purpose you describe, you may want to look into the bloc pattern and it's implementation as flutter-bloc. It might seem easier to do the user in this way by hand, but once you reach the point where you have multiple of those streams, you may want a more structured approach.
You can use
Stream<User> get user async*{
yield .................. ;
}
you can use yield keyword when you want to return stream object.
2nd way you can use a stream controller. You can add value in controller and
listen wherever you want to listen in your app there is no need to return stream

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'];
}