0

I have a listview where each item is one document from a firestore collection. I would like to tap the item and pass the document information to a details page.

This is how I am retrieving document information within the first stream:

child: Text(streamSnapshot.data.docs[index]['event_title'],

This is how I'm attempting to send the data to the next page:

child: GestureDetector(
                          onTap: () {
                            Navigator.pushNamed(context, EventPage.id, arguments: streamSnapshot.data.docs[index]);
                          },

I'm lost as to how to receive the passed data:

    class _EventPageState extends State<EventPage> {
  @override

final db = FirebaseFirestore.instance;
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments;
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('event_title'),
      ),
      child: Column(

I know I need a StreamBuilder on the next page, but do you have any insight on how to make that stream show only the passed in document?

2 Answers2

0

Why don't you use Provider instead? It'll help you to avoid boiler plate and as you're using streams it'll let you handle information in a better way. Check about it here

  • Thanks for that input. Looks like Riverpod is the improved version of provider, and may be the way to go. Do you have any pointers or links to resources for how to do this? I'm quite new to coding, and while I will eventually figure it out, it might take me a while. – Ian Carberry Aug 17 '21 at 17:43
  • Actually that's the reason cause i recommended you Provider, it'll be easier for you to understand, i'd recommend you to read the documentation and check youtube tutorials at the same time... It's the best way to understand Provider i think, and then you can migrate to riverpod (As you said, Riverpod has the same base as provider) – App Developer Aug 18 '21 at 21:28
  • So I have been up to my ears in documentation and YouTube tutorials on provider and Riverpod, but I still have not found an answer to my question. I'm getting extremely frustrated, and the answer may be right in front of my face. Could you please answer my question, or direct me to an answer? The homepage shows a list view of firebase documents within a collection. I need to tap on one document and navigate to a details page with more information from that document. How do I link the two? – Ian Carberry Aug 22 '21 at 00:58
0

I have worked out an answer to this question. I'm sure there are several ways to do this, but here's mine:

The key is to pass the firestore document ID to the next page. In this example code, I pass streamSnapshot.data.docs[index].id.toString() as a parameter to a custom widget. I've located my named route within that widget.

StreamBuilder(
    stream: FirebaseFirestore.instance
        .collection('events')
        .where('start_date', isGreaterThanOrEqualTo: DateTime.now())
        .snapshots(),
    builder: (context, AsyncSnapshot streamSnapshot) {

      if (!streamSnapshot.hasData) {
        return SizedBox(
          height: 250,
          child: Center(
            child: CircularProgressIndicator(),
          ),
        );
      } else
        return SizedBox(
          height: 250,
          child: ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: streamSnapshot.data.docs.length,
            itemBuilder: (ctx, index) =>

                EventListHorizontalTile(

                //passes the document ID as a string down to the horizontally scrollable tile,
                //where we push a named route with the docID string as an argument

                firestoreDocID: streamSnapshot.data.docs[index].id.toString(),

                  image: streamSnapshot.data.docs[index]['main_image'],
                  name: streamSnapshot.data.docs[index]['name'],
              ),
          ),
        );
    }),

I then created a class to pass as an argument through a named route.

class Events {
  final String firestoreDocID;

  Events({
    required this.firestoreDocID,

  });

}

Now, within my EventListHorizontalTile widget:

class EventListHorizontalTile extends StatelessWidget {
  const EventListHorizontalTile({
    Key? key,

    required this.name,
    this.firestoreDocID = '',

  }) : super(key: key);

  final String name;
  final String firestoreDocID;

  @override
  Widget build(BuildContext context) {
return GestureDetector(

        onTap: () {

//Here I am pushing a named route with an argument, using that Events class I made earlier.

          Navigator.pushNamed(context, EventPage.id, arguments: Events(firestoreDocID: firestoreDocID));

        },

//child: The rest of the list tile widget

),

Now we have to write a bit of code in the EventPage to receive the argument.

class EventPage extends StatefulWidget {
  const EventPage({
    Key? key,
  }) : super(key: key);

  static String id = 'EventPage';

  @override
  _EventPageState createState() => _EventPageState();
}

class _EventPageState extends State<EventPage> {
  @override
  Widget build(BuildContext context) {


//This is how we receive the argument.
    final args = ModalRoute.of(context)!.settings.arguments as Events;

    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(),
      child: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [

//Some text to see if the string made it.
            Text(args.firestoreDocID),

]),
),
);
}
}

And that's it! Once you have that document ID in your new page, you can call a Streambuilder like this:

StreamBuilder(
              stream: FirebaseFirestore.instance
                  .collection('events')
                  .doc(args.firestoreDocID)
                  .snapshots(),
David Buck
  • 3,752
  • 35
  • 31
  • 35