How use the Current Id of an user in .doc() - flutter

I'm setting an User profile and I have a collection in my firestore which contain first 'users', in this I have the ID of this user and finally I can display name, uid etc.
The problem is I want to print that name in my front end but I can't access this collection because I don't know how to use the current uid in my .doc(uid), (uid is undefined), I used a future method to get the uid but I don't know how to connect these.
Hope you help me !
this is my frontend code
FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(uid)
.get(), //tryna to use that collection but uid is not defined correctly
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
var name = snapshot.data as DocumentSnapshot;
return Text(name['displayName'],
);
} else {
return Text("Loading...");
}
},
)
and my provider current User Id code
Future<String> inputData() async {
final User? user = _auth.currentUser;
final uid = user!.uid;
// here you write the codes to input the data into firestore
return uid;
}
I've updated frontend code here:
FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.get(), //tryna to use that collection but uid is not defined correctly and I need a void but
// I have one in my auhtprovider
//solution ? create id from here : use my provider
builder: (context, snapshot) {
if (snapshot.hasData)
return Text("Loading...");
if (snapshot.data == null) {
print('Document does not exist on the database');
}else{
return Text("Researching data...");
}
if (snapshot.connectionState == ConnectionState.done) {
var name = snapshot.data as DocumentSnapshot;
return Text(name['displayName'],
);
} else {
return Text("Loading..");
}
},
)
and UID ?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
Future userSetup(String displayName) async {
CollectionReference users = FirebaseFirestore.instance.collection('Users');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser!.uid.toString();
await users.doc(uid).set({'displayName': displayName, 'uid': uid });
final result = await users.doc(uid).get();
final data = result.data() as Map<String, dynamic>;
return data['displayName'];
}
Plus a photo of my firestore document :

To use the current user's UID in the read operation, do:
.doc(FirebaseAuth.instance.currentUser.uid)
The error you get after that, makes it sound like there is no document for the current user, which you code doesn't handle.
You'll need to check if (snapshot.hasData) before accessing snapshot.data, to ensure the AsyncSnapshot is done communicating with the database.
Then after that check if the document exists with if (snapshot.data!.exists) before accessing snapshot.data!.data().
Note that is pretty much exactly what the code in the documentation on reading data once does, so I highly recommend checking that out (again if needed).

Related

How to get snapshot from groupScreen? flutter firebase

I have created a group screen in my flutter app and when I hit the create button it create a group as described is code:
//Create group
Future<String> createGroup(String groupName1, userUid) async {
String retVal = "error";
List<String> members = [];
try {
members.add(userUid);
DocumentReference docRef;
docRef = await firestore.collection("groups").add({
'name': groupName1,
'leader': userUid,
'members': members,
'groupCreate': Timestamp.now(),
});
retVal = "success";
} catch (e) {
// ignore: avoid_print
print(e);
}
return retVal;
}
I am stuck in getting the snapshot from my FBbackend. I want to get the info and display is on my group screen. How can I achieve that?
I have try to get the snapshot but it says Text("..."). I think the problem is that the value of DocumentReference? docRef; is empty, but I don’t know how to fixed it.
code:
DocumentReference? docRef;
docRef == null
? const Text('Error No Group Name Found!!')
: // 👈 handle null here
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance
.collection('groups')
.doc(docRef!.id)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return const ErrorScreen();
}
return Center(
child: Text((snapshot.data
as DocumentSnapshot<
Map<String, dynamic>>)['name']),
);
}),

Flutter Firestore returns error without any problem in the code

The following code returns error "NoSuchMethodError"
StreamBuilder(
stream: SalaryService.getSingle(),
builder: (_, snapshot) {
if (snapshot.data() != null) {
print('step 3');
return Text(
snapshot.data['value'].toString(),
);
} else {
return Text(
"Nil",
);
}
},
),
class SalaryService {
static Stream<DocumentSnapshot> getSingle() {
Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
.doc(userId + '/salary' + todayYM)
.snapshots();
snapshot.forEach(
(element) {
// prints all the documents available
// in the collection
print(element.data().toString());
// print((element.data() != null).toString());
},
);
return snapshot;
}
}
The cloudstore document does not exist to begin with until the user updates his salary hence the if else used.
P.S.: I am a rookie
Two things:
It is best practice to check whether the QueryDocumentSnapshot returned has data, plus check whether the document reference exists first by casting it as a DocumentSnapshot as opposed to pull the data straight up, as in:
if (snapshot.hasData && (snapshot.data as DocumentSnapshot).exists) { // ... }
you cannot pull the properties out of the snapshot like snapshot.data['field'] without pulling the data out first as a Map<String, dynamic>; you at least have to do first is snapshot.data() (after checking that it exists), then pull the fields out of the returned map, as in:
Map<String, dynamic> docData = (snapshot.data as DocumentSnapshot).data() as Map<String, dynamic>;
print(docData['value']);
Check this Gist for the full code (replace with your Firebase config settings at the top if you want to test it by running it on DartPad.dev.

How to order Firestore documents in list form based on int values in flutter

I currently have a list of documents that each contain an int value called plastics. Currently, the list only displays the documents in order by when it was added to the collection, but I want to be able to order the documents based on the int value within each one. I've looked around on the web and I've only found tutorials mostly on ordering timestamps. Is there any documentation or sources on this matter? Here is the code situation I'm working with:
Firstly, in my app users can join groups, and when they do so they bring along their name and int data which is then stored in documents for each user.
Future<String> joinGroup(String groupId, String userUid, String displayName,
String plastics) async {
String retVal = 'error';
List<String> members = List();
try {
members.add(displayName);
await _firestore.collection('Groups').doc(groupId).update({
'members': FieldValue.arrayUnion(members),
});
final uid = FirebaseAuth.instance.currentUser.uid;
await _firestore.collection('UserNames').doc(uid).update({
'groupId': groupId,
});
//Below me is the code for doing so
await _firestore
.collection("Groups")
.doc(groupId)
.collection("Members")
.doc(userUid)
.set({'displayName': displayName, 'plastics': plastics});
retVal = 'success';
} catch (e) {}
return retVal;
}
I then take that code access the documents and put them in a list.
#override
Widget build(BuildContext context) {
final CollectionReference users = firestore.collection('UserNames');
final String uid = auth.currentUser.uid;
return FutureBuilder(
future: users.doc(uid).get(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final result = snapshot.data;
final groupId = result.data()['groupId'];
return FutureBuilder<QuerySnapshot>(
// <2> Pass `Future<QuerySnapshot>` to future
future: FirebaseFirestore.instance
.collection('Groups')
.doc(groupId)
.collection('Members')
.get(),
builder: (context, snapshot) {
if (snapshot.hasData) {
// <3> Retrieve `List<DocumentSnapshot>` from snapshot
final List<DocumentSnapshot> documents = snapshot.data.docs;
return ListView(
children: documents
.map((doc) => Card(
child: ListTile(
title: Text(doc['displayName']),
subtitle: Text(doc['plastics'].toString()),
),
))
.toList());
} else if (snapshot.hasError) {
return Text('Its Error!');
}
});
}
});
}
Is there a specific function needed so that the documents in the Member collection are listed based on the numerical value of the plastics?
You can use orderBy to sort your results.
FirebaseFirestore.instance
.collection('Groups')
.doc(groupId)
.collection('Members')
.orderBy('plastics', descending: true)
.get()

Move method to streambuilder

List<Photo> imgList = [];
Future getCarouselWidget() async {
var firestore = Firestore.instance;
QuerySnapshot qn =
await firestore.collection("history").getDocuments();
List pics = qn.documents
.map((it) => Photo(it['photo'].toString(), it['name'].toString(), it['address'].toString()))
.toList();
return imgList = pics;
}
Hi all, when I make changes in my DB I dont see them in my app? can anybody help me or guid me how to wire this to stream builder or query the stream
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('swimfinderlakes')
.snapshots(),
builder: (context, snapshot) {
Every time Firestore has a change, it'll trigger the StreamBuilder. U can then access the most recently update with the snapshot on the builder method. Then you can use it to update the ui accordingly.
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('swimfinderlakes')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.hasData) {
List pics = qn.documents
.map((it) => Photo(it['photo'].toString(),
it['name'].toString(), it['address'].toString())).toList();
return pics;
}
} else {
return CircularProgressIndicator();
}
}

How to get inside data in Future<Map<dynamic, dynamic>>?

Future<Map> returnUserMap() async {
final FirebaseUser currentUser = await _auth.currentUser();
Map userMap = {
"UserName": currentUser.displayName,
"UserEmail": currentUser.email,
"UserUrl": currentUser.photoUrl
};
print("1");
print(userMap);
return userMap;
}
return value type is Instance of 'Future>'.
I want to get a UserName, how can I do it?
Your function returnUserMap() returns a Future<Map>. I suspect that the error you describe is not in the code snippet you copied.
Whenever the task to be performed may take some time, you will receive a future. You can wait for futures in an async function with await.
It is therefore recommended to use a so-called FutureBuilder in your build() function:
FutureBuilder<FirebaseUser>(
future: _auth.currentUser(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
final FirebaseUser user = snapshot.data;
if (user.displayName == null || user.displayName.isEmpty())
return text(currentUser.email); // display email if name isn't set
return text(currentUser.displayName);
}
if (snapshot.hasError) {
return text(snapshot.error);
}
return text('loading...');
},
),
If you want to have the displayName outside your build() function, the following code should do the job when you are inside of an async function:
final FirebaseUser user = await _auth.currentUser();
final String displayName = user.displayName;
print('the displayName of the current user is: $displayName');
And this code when you are in a normal function:
_auth.currentUser().then((FirebaseUser user) {
String displayName = user.displayName;
print('displayName: $displayName');
}).catchError((error) {
print('error: ' + error.toString());
});
I think it's worth watching the following video for further understanding:
Async/Await - Flutter in Focus