skip to Main Content

I’m attempting display data from two diffrent collections within firestore , I treied to nest both streambuilds so i can particulary display the data as one stream , however I keep on getting the error bad state field doesnt exist with doc snapshot how can i fixing thus error , or is there another much more effective method i can use to display data from two diffrent collections in one class?

below is screenshot of the data(s) i want to display:
enter image description here
enter image description here

class OrderStream extends StatelessWidget {
  static const String route = "/Order";

  final CollectionReference meal =
      FirebaseFirestore.instance.collection("menu");
  final CollectionReference profile =
      FirebaseFirestore.instance.collection("users");

  OrderStream({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: StreamBuilder(
            stream: profile.snapshots(),
            builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
              return StreamBuilder(
                stream: meal.snapshots(),
                builder:
                    (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
                  if (!streamSnapshot.hasData) {
                    return const SizedBox(
                      height: 250,
                      child: Center(
                        child: CircularProgressIndicator(),
                      ),
                    );
                  } else {
                    return ListView.builder(
                        itemCount: streamSnapshot.data!.docs.length,
                        itemBuilder: (context, index) {
                          final DocumentSnapshot documentSnapshot =
                              streamSnapshot.data!.docs[index];
                          return Column(
                             children: [
                            Text( documentSnapshot['price'],)
                            Text( documentSnapshot['name'],)
                             

                           ]
                              ),
                            ),
                      }

2

Answers


  1. This is probably happening due to similar name for both snapshots.

    The best way to check this is by renaming the snapshot for individual Streambuilder().

    StreamBuilder(
                stream: profile.snapshots(),
                builder: (context, AsyncSnapshot<QuerySnapshot> profileStreamSnapshot) {
                  return StreamBuilder(
                    stream: meal.snapshots(),
                    builder:
                        (context, AsyncSnapshot<QuerySnapshot> mealStreamSnapshot) {
                      if (!streamSnapshot.hasData) {
                        //modified (renamed snapshot variable) code here
                      }
    
    Login or Signup to reply.
  2. You can merge those two streams into 1 using library like rxdart which has combineLatest2 method although you can also use something like StreamZip to get the same effect.

    I have used rxdart combineLatest2 as follows:

    import 'package:rxdart/rxdart.dart';//import ⇐
    
    class MyHomePage extends StatelessWidget {
      final CollectionReference profile =
          FirebaseFirestore.instance.collection("users");
      final CollectionReference meal =
          FirebaseFirestore.instance.collection("menu");
      MyHomePage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: StreamBuilder(
              stream: Rx.combineLatest2(profile.snapshots(), meal.snapshots(),
                  (QuerySnapshot profileSnapshot, QuerySnapshot mealSnapshot) {
                return [...profileSnapshot.docs, ...mealSnapshot.docs];
              }),
              builder: (context, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
                if (!snapshot.hasData) {
                  return const SizedBox(
                    height: 250,
                    child: Center(
                      child: CircularProgressIndicator(),
                    ),
                  );
                } else {
                  return ListView.builder(
                    itemCount: snapshot.data!.length,
                    itemBuilder: (context, index) {
                      final DocumentSnapshot documentSnapshot =
                          snapshot.data![index];
                      final Map<String, dynamic> data =
                          documentSnapshot.data() as Map<String, dynamic>;
                      if (data.containsKey("price") && data.containsKey("name")) {
                        return Column(
                          children: [Text(data["price"]), Text(data["name"])],
                        );
                      } else {
                        return Container();
                      }
                    },
                  );
                }
              }),
        );
      }
    }
    

    You can also use Stream.merge() as follows:

    final Stream<QuerySnapshot> mealsStream = meal.snapshots();
    final Stream<QuerySnapshot> profilesStream = profile.snapshots();
    //.. All that Scaffold stuff
    stream: Stream.merge([mealsStream, profilesStream]),
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search