Store array from cloud firestore into variable - firebase

I have a collection called users. Each document has the ids of posts they have saved in an array. Is it possible to put this array into a variable and have it in a Text() widget? Essentially the text widget output would look like this on screen oMqSYa97CteaDr19lZ5Ga6WO4jn8oPJREOcJWLI2.
I have searched for this solution, but haven't found any luck.
I've tried a few things, but usually end up with Instance of 'Future DocomentSnapshot'

you should share your code for us to learn what you did and why do you face with that oMqSYa97CteaDr19lZ5Ga6WO4jn8oPJREOcJWLI2. However, firstly, you should create a model like that
class UserData {
final String uid;
final String name;
final String sugars;
final int strength;
UserData({ this.uid, this.sugars, this.strength, this.name });
}
and an instance;
final CollectionReference UsersCollection =
FirebaseFirestore.instance.collection('users');
and you can use it like that ;
UserData _userDataFromSnapshot(DocumentSnapshot snapshot) {
return UserData(
uid: uid,
name: snapshot.data()['name'],
sugars: snapshot.data()['sugars'],
strength: snapshot.data()['strength'],
);
}
Stream<UserData> get userData {
return UsersCollection.doc(uid).snapshots().map(_userDataFromSnapshot);
}
finally;
UserData userData = snapshot.data.sugars;

Related

Firebase Flutter Riverpod: How do I get the documentID from Firebase when using Riverpod to map values across a model? Code Included

I need to get the documentID of my documents in a firebase collection. The documentID is NOT stored as a field within the document. The ID was chosen by Firebase on import.
The other fields like name, phone, fullAddress, all display perfectly. How do I tap into the auto-generated docID using my Map/Model?
Any guidance is greatly appreciated.
Services:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'restaurant_model.dart';
final restaurantProvider = StreamProvider.autoDispose((ref) {
final service = ref.watch(restaurantServiceProvider);
return service.restaurantModel();
});
final restaurantServiceProvider = Provider<RestaurantService>((ref) {
final firebase = FirebaseFirestore.instance;
return RestaurantService(firebase);
});
class RestaurantService {
final FirebaseFirestore _firebase;
RestaurantService(this._firebase);
Stream<List<RestaurantModel>> restaurantModel() {
return _firebase.collection('restaurantsPensacola').snapshots().map((event) => event.docs.map((e) => RestaurantModel.fromFirebase(e.data())).toList());
}
}
Model
import 'package:cloud_firestore/cloud_firestore.dart';
class RestaurantModel {
final String? name;
final String? phone;
final String? fullAddress;
final String? yearsInBusiness;
final String? priceRange;
final String? websiteLink;
final String? documentID;
RestaurantModel({
required this.name,
required this.phone,
required this.fullAddress,
required this.yearsInBusiness,
required this.priceRange,
required this.websiteLink,
required this.documentID,
});
factory RestaurantModel.fromFirebase(Map<String, dynamic> restaurantModel) {
return RestaurantModel(
name: restaurantModel['name'],
phone: restaurantModel['phone'],
fullAddress: restaurantModel['fullAddress'],
yearsInBusiness: restaurantModel['yearsInBusiness'],
priceRange: restaurantModel['priceRange'],
websiteLink: restaurantModel['websiteLink'],
//THIS IS WHERE I AM LOST AS THIS GENERATES ERROR
//Instance members can't be accessed from a factory constructor.
documentID: restaurantModel[documentID],
);
}
}
The document ID can be accessed via e.id. For your RestaurantModel, you would probably want to rename it to restaurantId to be more accurate as to what it is describing, and just save the auto-generated document ID as the restaurantId at creation. You could also generate your own unique ID (with uuid package or something similar) and create a new document with that ID.
Example:
Future<dynamic> createRestaurantRecord(
String id, Map<String, dynamic> data) async {
return await _firestore.doc('restaurants/$id').set(data);
}
Your factory will not work as the documentID is not automatically stored with the rest of the doc's data.
I was able to meet with my mentor and was shown I can get the ID from Firebase by adding e.id after e.data.
Stream<List<RestaurantModel>> restaurantModel() {
return _firebase.collection('restaurantsPensacola').snapshots().map(
(event) => event.docs.map((e) => RestaurantModel.fromFirebase(e.data(), e.id)).toList());
}
Then, it was recommended that I change the names slightly to make it easier to differentiate values. You'll see how I incorporated the documentID from Firebase.
import 'package:cloud_firestore/cloud_firestore.dart';
class RestaurantModel {
final String? name;
final String? phone;
final String? fullAddress;
final String? yearsInBusiness;
final String? priceRange;
final String? websiteLink;
final String? id;
RestaurantModel({
required this.name,
required this.phone,
required this.fullAddress,
required this.yearsInBusiness,
required this.priceRange,
required this.websiteLink,
required this.id,
});
factory RestaurantModel.fromFirebase(
Map<String, dynamic> restaurantModel, String documentIDFromFirebase) {
return RestaurantModel(
name: restaurantModel['name'],
phone: restaurantModel['phone'],
fullAddress: restaurantModel['fullAddress'],
yearsInBusiness: restaurantModel['yearsInBusiness'],
priceRange: restaurantModel['priceRange'],
websiteLink: restaurantModel['websiteLink'],
id: documentIDFromFirebase,
);
}
}

how to read a single files in firebase

so i want to read the roles of my users, i know how to read collection and document,but how to read a field from the documents?
this what i've been trying,
#override
void readRole(){
final path = APIPath.role(uid);
final reference = FirebaseFirestore.instance.collection(path);
final snapshots = reference.snapshots();
snapshots.listen((snapshot) { snapshot.docs.forEach((snapshot) => print(snapshot.data()));
});
}
static String role (String uid) => 'users/$uid';
Firestore doc.data() has type of Map<String, dynamic> , meaning Json.
so you could try something like this:
final Map<String, dynamic> data = snapshot.data();
final String role = data['role'];
But the best way would be to create a user entity and use Json_serializable: https://pub.dev/packages/json_serializable
and convert the firestore data object to your user entity;
But by checking your role() function, i am not sure to understand it correctly, user's role is just the string 'users/$uid' ?

Failed to get uid to use within DatabaseService class in flutter

I face a problem where I can't get the current user ID from my firebase. I've already make that every new user will have their own collection based on the UID like this:
void addImagetoFirestore() async {
final CollectionReference imageData = Firestore.instance.collection(uid);
This is my DatabaseService class
class DatabaseService {
final String uid;
DatabaseService({this.uid});
String useruid;
final FirebaseAuth auth = FirebaseAuth.instance;
//Collection reference
final CollectionReference warrantyCollection =
Firestore.instance.collection('user id here');
List<Picture> _warrantyListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
return Picture(
name: doc.data['product name'],
info: doc.data['info'],
url: doc.data['url'],
uid: doc.data['uid']);
}).toList();
}
Future updateUserData(String name) async {
return await warrantyCollection.document(uid).setData({'name': name});
}
Stream<List<Picture>> get picture {
return warrantyCollection.snapshots().map(_warrantyListFromSnapshot);
}
}
I've tried referring to this,
but it seem like I can't just make something like
final CollectionReference warrantyCollection = Firestore.instance.collection(useridmethod());
are there any other alternative that I can try?
Instead of getting uid as a parameter to class, fetch it in constructor because in your case final FirebaseAuth auth = FirebaseAuth.instance; is useless as I see.
try this;
DatabaseService(){
userId = auth.currentUser.uid;
}

Unable to Return Queried Data From Firebase (Flutter/Dart)

Context: I'm trying to query and return a String (imgUrl) from Firebase. I'm always able to print the string inside the query, but the returned value is always null. I'm wondering if my query is wrong and am not sure what best practices are.
Database Outline:
Query Function:
This is the code under our DatabaseService() class, which contains all database queries and updating functions.
String getImageUrl(String _uid) {
String _imgUrl;
Firestore.instance
.document('users/$_uid')
.get()
.then((value) => _imgUrl = value['imgUrl']);
return _imgUrl;
}
Main:
getImageUrl() is called under setImage(). The toast under setImage always returns null and so does the code under it.
String _uid;
// Sets variable '_uid' to the uid of the current user
// Gets called in initstate
Future _getUid() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
_uid = user.uid;
}
// Sets the profile photo. If there is no existing profile photo online,
// grab the image on the device. If there is no image online OR on the device,
// Display the default image
void setImage(String url) {
// Get the url that's stored in the db
String _tempUrl = DatabaseService().getImageUrl(_uid); // always ends up being null
Fluttertoast.showToast(msg: "_tempUrl: $_tempUrl");
// Rest of the function
}
#override
void initState() {
super.initState();
_getUid();
}
Please let me know what to do to fix this as it's driving me crazy. Thanks in advance.
Change the method to the following:
Future<String> getImageUrl(String _uid) async {
String _imgUrl;
DocumentSnapshot value =
await Firestore.instance.document('users/$_uid').get();
_imgUrl = value['imgUrl'];
return _imgUrl;
}
use async/await to wait for the future to finish, and then call it like the following:
void setImage(String url) async{
// Get the url that's stored in the db
String _tempUrl = await DatabaseService().getImageUrl(_uid); // always ends up being null
Fluttertoast.showToast(msg: "_tempUrl: $_tempUrl");
// Rest of the function
}

Firestore query to variable to populate shared preferences

New to Flutter, and although I've been around code for many years, this is my first time actually developing. I've been trying to figure out how to query the Cloud Firestore and map one of those properties to a shared preference. Since my app is talking to the cloud firestore when a user logs in anyway, I feel like I can update my shared preferences with a few fields that will save me from having to call firestore everytime I want to retrieve that piece of information.
I created a class that represents the collection layout in the firestore
class FirestoreUser {
FirestoreUser(this.aboutMe, this.nickname);
final String aboutMe;
final String nickname;
factory FirestoreUser.fromMap(Map<String, dynamic> data) {
if (data == null) {
return null;
}
final String aboutMe = data['aboutMe'];
final String nickname = data['nickname'] ?? '';
return FirestoreUser(aboutMe, nickname);
}
Map<String, dynamic> toMap() {
return {
'aboutMe': aboutMe,
'nickname': nickname,
};
}
}
I also have a function that writes data to the Firestore collection. That works just fine.
What I'm having a hard time with is how do I query for "aboutMe" in the collection above? I'm using
a provider to get the uid, but how do I do something like this:
aboutMe = Firestore.query.tothatdocument
Here's what I have been working on so far:
final user = Provider.of<User>(context, listen: false);
final firestore = Provider.of<FirestoreService>(context, listen:false);
final firebaseUser = await FirebaseAuth.instance.currentUser();
final QuerySnapshot result = await Firestore.instance.collection('users').where('id', isEqualTo: firebaseUser.uid).getDocuments();
final List<DocumentSnapshot> documents = result.documents;
SharedPreferences prefs = await SharedPreferences.getInstance();
And I want to do something like this:
prefs.setString('aboutMe', 'thatAboutMeVariable);
Is this possible? I think I'm missing capturing the stream as a snapshot? but not to sure.
Thanks again!
I ended up creating a new class with functions to retrieve the fields that I wanted. I then assigned a variable to the results of that function.
Here's the call:
aboutMe = await FirestoreUserService(id: widget.id).getAboutMeFromFirestore();
Here's the class and function:
class FirestoreUserService {
FirestoreUserService({#required this.id});
final FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference users;
String aboutMe;
Future getAboutMeFromFirestore() async {
DocumentSnapshot ds = await FirebaseFirestore.instance.collection('users').doc(id).get();
aboutMe = ds.data()['aboutMe'];
//print('\nFirestore aboutMe is value: $aboutMe');
return aboutMe;
}
}

Resources