who-aditya-nawandar
who-aditya-nawandar

Reputation: 1344

Cannot retrieve data from nested collection

_getDataRowsForCompletedExerciseSets(workoutId) async {
try {
  List listOfExercises = await FirebaseFirestore.instance
      .collection('users')
      .doc(currentUser!.uid)
      .collection("workouts")
      .doc(workoutId)
      .collection("exercises")
      .get()
      .then((snapShot) => snapShot.docs);

  for (int i = 0; i < listOfExercises.length; i++) {
    FirebaseFirestore.instance
        .collection('users')
        .doc(currentUser!.uid)
        .collection("workouts")
        .doc(workoutId)
        .collection("exercises")
        .doc(listOfExercises[i].doc.id.toString())
        .collection("sets")
        .snapshots()
        .listen(_createListOfExerciseSets);
  }

  setState(() {
    for (ExerciseSet set in listOfExerciseSets) {
      //print(set.weight);
      completedExerciseSetRows.add(DataRow(cells: [
        DataCell(Text(setCount.toString())),
        //const DataCell(VerticalDivider(thickness: 5)),
        DataCell(Text(set.weight.toString())),
        //const DataCell(VerticalDivider(thickness: 5)),
        DataCell(Text(set.reps.toString())),
        //const DataCell(VerticalDivider(thickness: 5)),
        DataCell((isSetToFailure == true) ? Icon(Icons.check) : Icon(null))
        //const DataCell(VerticalDivider(thickness: 5)),
      ]));
    }
  });
} on Exception catch (_, e) {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      content: Text(e.toString()),
      duration: Duration(milliseconds: 1000),
    ),
  );
}
return Container();

}

    _createListOfExerciseSets(QuerySnapshot snapshot) {
  var docs = snapshot.docs;
  for (var doc in docs) {
    listOfExerciseSets.add(ExerciseSet.fromFireStore(doc));
  }
  print('EXERCISE SETS = ' + listOfExerciseSets.toString());
}

I have the following db structure:

users-->{id}-->workouts-->{id}-->exercises-->{id}-->sets-->{id}--fields

I am trying to get the exercises for a particular workout(id) along with the sets(including fields) for each exercise. The listOfExercises is always empty (0 items). There are no errors showing either.

Upvotes: 0

Views: 85

Answers (2)

who-aditya-nawandar
who-aditya-nawandar

Reputation: 1344

Here is what I have right now:

     Widget build(BuildContext context) {
    var exercisesRef = usersRef
        .doc(currentUser!.uid)
        .collection('workouts')
        .doc(workoutId)
        .collection('exercises');
    return FutureBuilder<QuerySnapshot>(
      future: exercisesRef.get(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.active:
            return const Center(
              child: kCPI,
            );
          case ConnectionState.waiting:
            return const Center(
              child: kCPI,
            );
          case ConnectionState.none:
            return const Center(
              child: kCPI,
            );
          case ConnectionState.done:
            if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else if (!snapshot.hasData) {
              //print('WORKOUTID = ' + workoutId);
              return const Text("Document does not exist");
            } else if (snapshot.hasData &&
                snapshot.connectionState == ConnectionState.done) {
              final exercises = snapshot.data!.docs;
              List<Widget> completedExercisesWidgetsList = [];

              final _controller = ScrollController();

              // for loop - loop through all the exercises for the current workout
              for (var doc in exercises) {
                bool isRowsGeneratedForPreviousExercises = false;
                dataRowsForCompletedExercises = [];
                var setList = [];
                Map<String, dynamic> exercise;
                var exerciseName = '';
                exercise = doc.data() as Map<String, dynamic>;
                setList = exercise['sets'];
                exerciseName = exercise['name'];

                //loop through the sets for the exercise

                for (var set in setList) {
                  var setNumber = 0;
                  var weight = '';
                  var reps = '';
                  var isToFailure = false;
                  setNumber = setList.indexOf(set) + 1;
                  weight = set['weight'].toString();
                  reps = set['reps'].toString();
                  isToFailure = set['isToFailure'];
                  if (isRowsGeneratedForPreviousExercises == false) {
                    _generateDataTableRowsForCompletedExercises(
                      setNumber,
                      weight,
                      reps,
                      isToFailure,
                    );
                  }
                }
                isRowsGeneratedForPreviousExercises = true;
                completedExercisesWidgetsList
                    .add(_completedExercisesDataTableWidget(exerciseName));
              } //for loop ends

              ///Return list of widgets - one widget for each completed exercise for the current workout
              return Column(
                mainAxisSize: MainAxisSize.max,
                children: [
                  Expanded(

                    child: ScrollConfiguration(
                      behavior: ScrollConfiguration.of(context).copyWith(
                        dragDevices: {
                          PointerDeviceKind.touch,
                          PointerDeviceKind.mouse,
                        },
                      ),
                      child: ListView(
                        shrinkWrap: true,
                        controller: _controller,
                        physics: const AlwaysScrollableScrollPhysics(),
                        scrollDirection: Axis.vertical,
                        children: completedExercisesWidgetsList,
                      ),
                    ),
                  ),
                ],
              );
            }
        }
        return const Text("There was a problem loading content.");
      },
    );
  }

And then simply generating DataTable rows from the data:

      void _generateDataTableRowsForCompletedExercises(
      setNumber, weight, reps, isToFailure) {
    dataRowsForCompletedExercises.add(
      DataRow(cells: [
        DataCell(Text(setNumber.toString())),
        DataCell(Text(weight)),
        DataCell(Text(reps)),
        DataCell(
            (isToFailure == true) ? const Icon(Icons.check) : const Icon(null)),
      ]),
    );
  }

Upvotes: 1

KRISHNU R S
KRISHNU R S

Reputation: 11

I believe your problem is where you use 'then'

Try this code and see the print output

var test = await FirebaseFirestore.instance
  .collection('users')
  .doc(currentUser!.uid)
  .collection("workouts")
  .doc(workoutId)
  .collection("exercises")
  .get()
print(test);

Upvotes: 0

Related Questions