Home > Net >  Display sub-collection in flutter Firebase
Display sub-collection in flutter Firebase

Time:08-18

I want to display the data of a sub-collection named "Profile". I get it that we need to query it differently, and I tried it, but it is not working out for me. First, I displayed the information from the documents of the mother collection "mentors", using StreamBuilder. Then passed it's data to a Widget I created. Then on the Widget I created, I performed another streamBuilder query for the subcollection of each document of the Mother Collection "mentors".

This is the code I used to display the documents on "mentors" collection, and is working fine.

final mentors = Expanded(
  child: Container(
    height: 250,
    margin: const EdgeInsets.only(left: 20, right: 20),
    child: StreamBuilder<QuerySnapshot>(
        stream: db_mentors,
        builder: (
          BuildContext context,
          AsyncSnapshot<QuerySnapshot> snapshot,
        ) {
          if (snapshot.hasError) {
            Fluttertoast.showToast(msg: "An Error Occured");
          }

          if (snapshot.connectionState == ConnectionState.waiting) {
            Fluttertoast.showToast(msg: "Loading");
          }

          final data = snapshot.requireData;
          return ListView.builder(
            itemCount: data.size,
            itemBuilder: ((context, index) {
              return mentorsWidget(
                "${data.docs[index]["uid"]}",
                "${data.docs[index]['name']}",
                "${data.docs[index]['specialty']}",
              );
            }),
          );
        }),
  ),
);

This here is the code I used to display the data from the subcollection of each document named "Profile". Which is also the widget I created.

Widget mentorsWidget(String uid, String name, String specialty) {
  return Container(
    margin: const EdgeInsets.all(5),
    width: size.width,
    decoration: const BoxDecoration(
        color: Color.fromARGB(255, 3, 42, 134),
        borderRadius: BorderRadius.only(
            topRight: Radius.circular(20),
            bottomRight: Radius.circular(20))),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        StreamBuilder(
            stream: FirebaseFirestore.instance
                .collection("mentors")
                .doc(uid)
                .collection("Profile")
                .snapshots(),
            builder: (
              BuildContext context,
              AsyncSnapshot<QuerySnapshot> snapshot,
            ) {
              if (!snapshot.hasData) {
                return SizedBox(
                  width: 80,
                  child: Image.asset("assets/Navigatu-icon.ico"),
                );
              } else {
                return ListView.builder(
                  itemCount: snapshot.data!.docs.length,
                  itemBuilder: ((context, index) {
                    String url = snapshot.data!.docs[index]['downloadURL'];
                    return SizedBox(
                      width: 80,
                      child: Image.network(url),
                    );
                  }),
                );
              }
            }),
        Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              margin: const EdgeInsets.only(top: 10, left: 5),
              child: Text(
                name,
                style: const TextStyle(
                    color: Colors.white,
                    fontSize: 20,
                    fontFamily: 'Roboto',
                    fontWeight: FontWeight.w500),
              ),
            ),
            Container(
              margin: const EdgeInsets.only(top: 15, bottom: 15, left: 5),
              child: Text(
                specialty,
                style: const TextStyle(
                  color: Colors.white,
                  fontFamily: 'Roboto',
                  fontWeight: FontWeight.w400,
                  fontSize: 12,
                ),
              ),
            ),
          ],
        )
      ],
    ),
  );
}

Here is the Collection Tree in my firebase: Firebase Collection Tree

Here is the display I want to achieve. The boat picture here supposedly must be a Image.network, with the url that is in the sub-collection, named "Profile". Mentor Field

As you can see in the code, I performed first the "final mentors", then performing streambuilder inside of it. So that I can get the datas of each document from the mother collection. Now I passed those data to the "mentorwidget" to display them in a proper way, but then I wanna use a Image.network, containing the data inside the sub-collection of each document in the mother collection. That's why I performed another streambuilder inside the mentorwidget to display the picture, or get the data of the sub-collection which is the url of the said picture.

CodePudding user response:

If the data doesn't get frequently updated or if you don't need to display the constant changes of it's value to the users then use FutureBuilder instead of StreamBuilder to query the value you want only once.

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<QuerySnapshot>(
        future: FirebaseFirestore.instance
            .collection('mentors')
            .doc('b23lt...[your desired document ID]')
            .collection('Profile')
            .get(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done &&
              snapshot.hasData) {
            return ListView.builder(
              itemCount: , // lenght of snapshot data,
              itemBuilder: (context, index) {
               //Here you can retrieve the data of each document
              },
            );
          }
          return const Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

CodePudding user response:

Update: I found the answer! thanks to Slender's answer, I managed to get the answer, here is the code.

FutureBuilder<QuerySnapshot>(
          future: FirebaseFirestore.instance
              .collection("mentors")
              .doc(uid)
              .collection("profile")
              .get(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              if (snapshot.data!.docs.isEmpty) {
                return SizedBox(
                  width: 80,
                  child: Image.asset("assets/Navigatu-icon.ico"),
                );
              } else if (snapshot.hasData) {
                // print(snapshot);
                return SizedBox(
                  width: 80,
                  child: Image.network(
                      "${snapshot.data!.docs[0]['downloadURL']}"),
                );
              }
            }
            // print(snapshot.data!.docs[0]['downloadURL']);
            return const SizedBox(
              width: 80,
              child: Center(
                child: CircularProgressIndicator(),
              ),
            );
          },
        ),
  • Related