skip to Main Content

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.

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search