Reputation: 15
I am stuck at trying to read the current user's data after storing it in Firestore. The page keeps showing a blank page instead of showing the actual data from Firestore.
I have created a model for the data like this
class Vital {
String id;
final String bloodSugar;
final String bloodPressure;
final String bodyTemp;
final DateTime? createdOn;
Vital({
this.id = '',
required this.bloodSugar,
required this.bloodPressure,
required this.bodyTemp,
required this.createdOn,
});
Map<String, dynamic> toJson() => {
'id': id,
'bloodSugar': bloodSugar,
'bloodPressure': bloodPressure,
'bodyTemp': bodyTemp,
"createdOn": Utils.fromDateTimeToJson(createdOn)
};
Vital.fromSnapShot(DocumentSnapshot<Map<String, dynamic>> snapshot)
: id = snapshot.id,
bloodSugar = snapshot.data()!["bloodSugar"],
bloodPressure = snapshot.data()!["bloodPressure"],
bodyTemp = snapshot.data()!["bodyTemp"],
createdOn = snapshot.data()!["createdOn"].toDate();
}
I have stored the data in Firestore using the below code
Future addVitals() async {
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = await auth.currentUser;
final uid = user?.uid;
final vitals = FirebaseFirestore.instance
.collection('vitalsign')
.doc(uid)
.collection("usersVitals");
final vital = Vital(
id: vitals.id,
createdOn: DateTime.now(),
bloodSugar: _bloodSugar.text,
bloodPressure: _bloodPressure.text,
bodyTemp: _bodyTemp.text);
final json = vital.toJson();
await vitals.add(json);
Navigator.push(
context, MaterialPageRoute(builder: (context) => VitalsSaved()));
}
Please note that users will be allowed to add their vitals everyday and what I want to achieve is to get the vitals of the current users in a separate page using stream builder.
This is what I would like to achieve
blood pressure
day1 day2
120/70 120/65 etc
blood glucose day1 day2 27 26 etc
this will be for a specific user and once another user login to the app, they should only get their own data from what they put in the input.
This is what I have tried to do in the stream of the stream builder
Stream<QuerySnapshot> readVitals() async* {
final FirebaseAuth auth = FirebaseAuth.instance;
final user = auth.currentUser;
final uid = user?.uid;
yield* FirebaseFirestore.instance
.collection('vitalsign')
.doc(uid)
.collection("userVitals")
.snapshots();
}
then I created a widget as follow to get data from firestore
Widget buildPressure(BuildContext context, DocumentSnapshot document) {
return Container(
child: Card(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
document["bloodSugar"],
style: TextStyle(fontSize: 20),
)
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [Text(document["bloodPressure"])],
),
),
],
),
),
);
}
Then lastly I use my widget in the streanbuilder as follow
stream: readVitals(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Text("Loading...");
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index) {
return buildPressure(context, snapshot.data.docs[index]);
});
}
return CircularProgressIndicator();
},
)
After everything I still get a blank page which means that I am not getting any data from Firestore despite having create data and add it in Firestore.
I have tried several ways but could not get it.
Upvotes: 0
Views: 67
Reputation: 471
I think you don't need to put .data()
in = snapshot.data()!
in model class part.
I will give you a simple example from code of my project that may help you move on..
class ReadsModel {
late String id;
late String firstName;
late String lastName;
late String father;
late String mother;
late String readDate;
late String subType;
late String counterNumber;
late String paymentStatus;
late int counterValue;
ReadsModel({
required this.id,
required this.firstName,
required this.lastName,
required this.father,
required this.mother,
required this.readDate,
required this.subType,
required this.counterNumber,
required this.paymentStatus,
required this.counterValue,
});
ReadsModel.fromMap(DocumentSnapshot data){
id = data.id;
firstName = data['FirstName'];
lastName = data['LastName'];
father = data['Father'];
mother = data['Mother'];
readDate = data['ReadDate'];
subType = data['Subscription type'];
counterNumber = data['CounterNumber'];
paymentStatus = data['Payment Status'];
counterValue = data['CounterValue'];
}
}
For the saving to Firestore part:
Future savingToFireStore() async {
await villagesCollectionRef
.doc()
.collection('Reads')
.doc(const Uuid().v4())
.set({
'FirstName': firstName,
'LastName': lastName,
'Father': father,
'Mother': mother,
'ReadDate': readDate,
'Subscription type': subType,
'Payment Status': 'unPaid',
'CounterValue': int.parse(readValueController.text),
'CounterNumber': counterNumber,
});
}
Then I create a list from the model type to store data in:
List<VillageModel> areaModel = <VillageModel>[].obs;
Then use this function to from GetX
package to stream data and get it "You can use Stream builder in the same way"
getReads() {
return villagesCollectionRef
.doc()
.collection('Reads')
.snapshots()
.listen((event) {
readsModel.clear();
for (var element in event.docs) {
readsModel.add(ReadsModel.fromMap(element));
}
});
}
Finally, in the UI part you can use the suitable widget to show data, for me I used ListView.builder()
.
I hope that helps you.
Upvotes: 1
Reputation: 72
Try changing your:
Stream<QuerySnapshot> readVitals() async* {
final FirebaseAuth auth = FirebaseAuth.instance;
final user = auth.currentUser;
final uid = user?.uid;
yield* FirebaseFirestore.instance
.collection('vitalsign')
.doc(uid)
.collection("userVitals")
.snapshots();
}
into:
Stream<Iterable<Vital>> readVitals() async* {
final FirebaseAuth auth = FirebaseAuth.instance;
final user = auth.currentUser;
final uid = user?.uid;
yield* FirebaseFirestore.instance
.collection('vitalsign')
.doc(uid)
.collection("userVitals")
.snapshots().map((event) =>
event.docs
.map((doc) => Vital.fromSnapshot(doc)));
}
This way you should return the values of the documents in the collection UserVitals
. Note that if this documents don't have all the fields (bloodSugar, bloodPressure, bodyTemp and createdOn) you are probably gonna get an error.
Upvotes: 1