Firestore CollectionReference with dynamic Path doesn't work - firebase

i'm trying to query a firestore collection with a dynamic path (user specific), it works hardcoded, but not dynamic with a variable, someone know the issue and can help?
Thanks in advance
final CollectionReference addressCollection =
Firestore.instance.collection('users/r9qClctByGXinYAmB2MqQNctgd53/addresses');
works.
This not:
final CollectionReference addressCollection =
Firestore.instance.collection('users/$userId/addresses');
userId is = r9qClctByGXinYAmB2MqQNctgd53
Full FirestoreDatabase code:
class FirestoreDatabase {
final _service = FirestoreService.instance;
static String userId;
void setUserId(uid) {
userId = uid;
}
final CollectionReference addressCollection =
Firestore.instance.collection('users/$userId/addresses');
// Adresses List Stream
Stream<List<Address>> get addressesStream {
return addressCollection.snapshots().map(_addressListFromSnapshot);
}
List<Address> _addressListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
return Address.fromMap(doc.data);
}).toList();
}
}

Related

The argument type 'Object? Function()' can't be assigned to the parameter type 'Map<String, dynamic>'

I created a class called 'tasks' and implement it. I edit gradle files for connecting with firebase. I gain some errors in my code. So please help me to solve this error.
class _MyHomePageState extends State<MyHomePage> {
late List<Task> items;
FirestoreService fireServ = new FirestoreService();
late StreamSubscription<QuerySnapshot> todoTasks;
#override
void initState() {
super.initState();
items= [];
todoTasks.cancel();
todoTasks=fireServ.getTaskList().listen((QuerySnapshot snapshot){
final List<Task> tasks=snapshot.docs
.map((documentSnapshot) => Task. fromMap(documentSnapshot.data))
.toList();
setState(() {
this.items = tasks;
});
});
}
This is my firestore class service
class FirestoreService {
Future<Task> createTODOTask(String taskname, String taskdetails,String taskdate,String tasktime,String tasktype) async {
final TransactionHandler createTransaction = (Transaction tx) async {
final DocumentSnapshot ds = await tx.get(myCollection.doc());
final Task task = new Task(taskname, taskdetails,taskdate,tasktime,tasktype);
final Map<String, dynamic> data = task.toMap();
await tx.set(ds.reference, data);
return data;
};
return FirebaseFirestore.instance.runTransaction(createTransaction).then((mapData) {
return Task.fromMap(mapData);
}).catchError((error) {
print('error: $error');
return null;
});
}
Stream<QuerySnapshot> getTaskList({int offset=0, int limit=0}) {
Stream<QuerySnapshot> snapshots = myCollection.snapshots();
if (offset != null) {
snapshots = snapshots.skip(offset);
}
if (limit != null) {
snapshots = snapshots.take(limit);
}
return snapshots;
}
}
You need to change:
documentSnapshot.data
to this:
documentSnapshot.data()
.data() is a method and not a property of the DocumentSnapshot object.

Storing a data permanent with Flutter

I am developing an app with Flutter and Firebase.
I want to store the _id with SharedPreferences permanently.
Therefore, i looked after it, but my code doesnt work at all. It always throws the error:
type 'Future' is not a subtype of type 'String'
Here is my code:
class Profile with ChangeNotifier {
String _id;
void setName(String name) {
const url =
'myurl';
http
.post(url, body: json.encode({'name': name, 'description': name}))
.then((response) {
_id = json.decode(response.body)['name'];
});
addID();
}
Future<void> updateName(String name, String id) async {
String url =
'myurl';
await http.patch(url,
body: json.encode({'name': 'Ein Titel', 'description': name}));
}
And here are my methods with the SharedPrefs:
String getID() {
return getIDOffline();
}
addID() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('id', _id);
}
getIDOffline() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//Return String
String stringValue = prefs.getString('id');
return stringValue;
}
You have use wrong method for return string so you have to change String getID() to Future<String> getID(). And you can use like this.
getValue()async{
String value = await getID();
}
When you use async always try to add also Future.
like :
Future<returnType> methodName() async { }
In your code try to change
String getID(){ } to Future<String>getID() async{ }

Create a sub collection from a nested list

Ive created a flutter app for keeping recipes.
Every recipe has a list of ingredient.
I create the recipe using a Recipe model and inside i have a list of ingredient.
By default when i save the above Recipe model to Firebase Firestore the Ingredient list is saved as an array.
I plan on expanding the concepts over time and would like to store the ingredient in a sub collection.
I am obviously able to iterate through the questions and add them as a document to their own collection, however this seems messy and likely to cause me problems in the future.
Is there a way in which i can specify that child models are created as a sub collection rather than an array?
Below is what im using currently to write the data
class FirestoreService {
FirestoreServiceNew._();
static final instance = FirestoreServiceNew._();
Future<void> setData({
#required String path,
#required Map<String, dynamic> data,
bool mergeBool = false,
}) async {
try {
final reference = FirebaseFirestore.instance.doc(path);
print('$path: $data');
await reference.set(data);
} catch (e) {
print('error: $e');
}
}
Future<void> bulkSet({
#required String path,
#required List<Map<String, dynamic>> datas,
bool merge = false,
}) async {
final reference = FirebaseFirestore.instance.doc(path);
final batchSet = FirebaseFirestore.instance.batch();
print('$path: $datas');
}
Future<void> deleteData({#required String path}) async {
final reference = FirebaseFirestore.instance.doc(path);
print('delete: $path');
await reference.delete();
}
Stream<List<T>> collectionStream<T>({
#required String path,
#required T builder(Map<String, dynamic> data, String documentID),
Query queryBuilder(Query query),
int sort(T lhs, T rhs),
}) {
Query query = FirebaseFirestore.instance.collection(path);
if (queryBuilder != null) {
query = queryBuilder(query);
}
final Stream<QuerySnapshot> snapshots = query.snapshots();
return snapshots.map((snapshot) {
final result = snapshot.docs
.map((snapshot) => builder(snapshot.data(), snapshot.id))
.where((value) => value != null)
.toList();
if (sort != null) {
result.sort(sort);
}
return result;
});
}
Stream<List<T>> requestStream<T>({
#required String path,
#required T builder(Map<String, dynamic> data, String documentID),
Query queryBuilder(Query query),
int sort(T lhs, T rhs),
}) {
Query query = FirebaseFirestore.instance.collection(path);
if (queryBuilder != null) {
query = queryBuilder(query);
}
final Stream<QuerySnapshot> snapshots = query.snapshots();
return snapshots.map((snapshot) {
final result = snapshot.docs
.map((snapshot) => builder(snapshot.data(), snapshot.id))
.where((value) => value != null)
.toList();
if (sort != null) {
result.sort(sort);
}
return result;
});
}
Stream<T> documentStream<T>({
#required String path,
#required T builder(Map<String, dynamic> data, String documentID),
}) {
final DocumentReference reference = FirebaseFirestore.instance.doc(path);
final Stream<DocumentSnapshot> snapshots = reference.snapshots();
return snapshots.map((snapshot) => builder(snapshot.data(), snapshot.id));
}
}
and my model
class Recipe {
String id;
List<Ingredient> ingredients;
String title;
String description;
Timestamp createdOn;
Recipe(
{this.id = '',
this.ingredients,
this.title,
this.description,
this.createdOn});
Recipe.fromData(Map<String, dynamic> json, String docid) {
id = docid ?? '';
title = json['title'];
description = json['description'];
createdOn = json['createdOn'];
if (json['questions'] != null) {
ingredients= new List<Ingredients>();
json['ingredients'].forEach((v) {
questions.add(new Ingredients.fromData(v, null));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['description'] = this.description;
data['title'] = this.title;
data['createdOn'] = this.createdOn;
if (this.ingredients != null) {
data['ingredients'] = this.ingredients.map((v) => v.toJson()).toList();
}
return data;
}
}
You can build a path to documents nested in subcollections by alternating calls to collection() and doc(), which return CollectionReference and DocumentReference objects respectively.
FirebaseFirestore.instance
.collection("top-level-collection")
.doc("document-id-1")
.collection("nested-subcollection")
.doc("document-id-2")

I want to get user id in a get function

Future<String> getCurrentUser() async {
final FirebaseUser user = await _auth.currentUser();
final uid = user.uid;
return uid;
}
I want to have user uid in the document but I cant get it .
Stream<List<RezervasyonListesi>> get rezervasonlarlistesi1 {
return rezervasyonCollectionRef
.document() // **In document I want refer to user uid ;**
.collection("rezerve")
.snapshots()
.map(_rezervasyonlistesifromsnap);
}
I tried this but didnt work
Stream<List<RezervasyonListesi>> get rezervasonlarlistesi {
getCurrentUser().then((value) {
return rezervasyonCollectionRef
.document(value)
.collection("rezerve")
.snapshots()
.map(_rezervasyonlistesifromsnap);
});
}
Stream<List< RezervasyonListesi>> is not a type of future because of that I cant use async in that function .Without ascyn how can I get my firebase user uid.
class of RezervasyonListesi
class RezervasyonListesi {
final String name;
final String address;
final String image;
final String rating;
final String description;
RezervasyonListesi(
{this.address, this.description, this.image, this.name, this.rating});
}
Try this.
Stream<List<RezervasyonListesi>> get rezervasonlarlistesi async*{
String currentUser = await getCurrentUser();
yield* rezervasyonCollectionRef.document(currentUser.uid).snapshots().map((snapshot){
return snapshot.data;
});
}

How can I get a value from firebase and and put it in a text in Flutter

I'm having a simple problem which is how to get specific values from database Firebase.
For example, I want to get the value of "name" and put it in text. How can I do that? Can you write a detailed code?
class _HomePageState extends State<HomePage> {
String myuid;
FirebaseUser currentUser;
// To get id
void _loadCurrentUser() {
FirebaseAuth.instance.currentUser().then((FirebaseUser user) {
setState(() { // call setState to rebuild the view
this.currentUser = user;
});
});
}
#override
void initState() {
super.initState();
_loadCurrentUser();
}
#override
Widget build(BuildContext context) {
myuid = currentUser.uid;
var getname;
Future<void> getName() async {
DocumentSnapshot ds =
await Firestore.instance.collection('users').document(myuid).get();
getname = ds.data['name'];
}
Try
String name;
Future<null> getName() async {
DocumentSnapshot document = await Firestore.instance.collection('users').document(FirebaseUser().uid).get();
name = document.data['name']
}
This is how you can get data from the Firestore Database Document once
val docRef = db.collection("users").document("mhPtwy..........")
docRef.get()
.addOnSuccessListener { document ->
if (document != null) {
Log.d(TAG, "DocumentSnapshot data: ${document.data}")
} else {
Log.d(TAG, "No such document")
}
}
.addOnFailureListener { exception ->
Log.d(TAG, "get failed with ", exception)
}
This is a kind of cheeky way to get the data and store it in a variable
var name;
Future<void> getName(){
DocumentSnapshot ds = await
Firestore.instance.collection('users').document(uid).get();
name = ds.data['name']
}
then just throw that in your text field
Text(name);

Resources