firebaseflutterflutter-streambuildermaterialpageroute

I want to Navigate to another page and parse with firestore data but how do I do that when I am using MaterialPageRoute?


I want to navigate from Products Page to a ProductDetail page but I am using data directly from firebase firestore. What do I put in the MaterialPageRoute as the arguments? I am also using StreamBuilder to get data snapshot from firebase. Below is the code. This is the products page.

class PopularRecipes extends StatefulWidget {
  const PopularRecipes({Key key}) : super(key: key);

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

class _PopularRecipesState extends State<PopularRecipes> {
  final Stream _productStream =
      FirebaseFirestore.instance.collection('products').snapshots();
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisAlignment: MainAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20),
          child: CustomText(
            text: 'Popular Recipes',
            size: 20,
          ),
        ),
        Container(
          height: 500,
          child: StreamBuilder(
              stream: _productStream,
              builder: (context, snapshot) {
                if (snapshot.data == null)
                  return Center(
                    child: CircularProgressIndicator(
                      backgroundColor: Colors.teal,
                    ),
                  );
                return ListView.builder(
                    itemCount: snapshot.data.docs.length,
                    itemBuilder: (context, index) =>
                        _popularWidget(context, snapshot.data.docs[index]));
              }),
        ),
      ],
    );
  }

  Widget _popularWidget(BuildContext context, DocumentSnapshot document) {
    return Stack(
      children: [
        Container(
          margin: EdgeInsets.fromLTRB(40, 5, 20, 5),
          height: 160,
          width: double.infinity,
          decoration: BoxDecoration(
              color: Colors.white, borderRadius: BorderRadius.circular(20)),
          child: Padding(
            padding: const EdgeInsets.fromLTRB(100, 20, 10, 20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    GestureDetector(
                      onTap: () => Navigator.push(context,
                          MaterialPageRoute(builder: (_) => DetailsScreen())),
                      child: Container(
                        width: 160,
                        child: Text(
                          document['name'],
                          style: TextStyle(
                              fontSize: 19.0, fontWeight: FontWeight.w600),
                          overflow: TextOverflow.ellipsis,
                          maxLines: 2,
                        ),
                      ),
                    ),
                    Column(
                      children: [
                        CustomText(
                          text: 'Ush.',
                          size: 14,
                          color: Colors.grey,
                        ),
                        CustomText(
                          text: document['price'],
                        ),
                      ],
                    )
                  ],
                ),
                RatingBarIndicator(
                  rating: document['rating'].toDouble(),
                  itemBuilder: (context, index) => Icon(
                    Icons.star,
                    color: Colors.amber.shade200,
                  ),
                  itemCount: 5,
                  itemSize: 15.0,
                  unratedColor: Colors.grey.shade300,
                  direction: Axis.horizontal,
                ),
                SizedBox(
                  height: 10,
                ),
                Container(
                  height: 40,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: [
                      Row(
                        children: [
                          for (var tag in document['tags'])
                            Container(
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(6),
                                color: Colors.grey.shade200,
                              ),
                              margin: EdgeInsets.only(right: 4),
                              child: Padding(
                                padding: const EdgeInsets.symmetric(
                                    horizontal: 8.0, vertical: 6),
                                child: Text(
                                  tag.toString(),
                                  style: TextStyle(
                                    fontSize: 14,
                                  ),
                                  textAlign: TextAlign.center,
                                ),
                              ),
                            )
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
        Positioned(
          top: 10,
          left: 20,
          bottom: 10,
          child: GestureDetector(
            onTap: () => Navigator.push(
                context, MaterialPageRoute(builder: (_) => DetailsScreen())),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(20),
              child: Image.network(
                document['image'],
                width: 110,
                fit: BoxFit.cover,
              ),
            ),
          ),
        )
      ],
    );
  }
}

This is the DetailsScreen page I want to go to when I click a specific product card.

class DetailsScreen extends StatefulWidget {
  const DetailsScreen({Key key}) : super(key: key);

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

class _DetailsScreenState extends State<DetailsScreen> {
  @override
  Widget build(BuildContext context) {
    return Text(document['name']);
  }
}

How do I pass data from the previous page to the details page with MaterialPageRoute when working with firebase data? Thank you.


Solution

  • In your DetailsScreen page add the product variable

    class DetailsScreen extends StatefulWidget {
      final DocumentSnapshot product;
      const DetailsScreen({Key key, @required this.product}) : super(key: key);
    
      @override
      _DetailsScreenState createState() => _DetailsScreenState();
    }
    
    class _DetailsScreenState extends State<DetailsScreen> {
      @override
      Widget build(BuildContext context) {
        return Text(widget.product['name']);
      }
    }
    

    And inside the onTap:

    GestureDetector(
      onTap: () => Navigator.push(context,
         MaterialPageRoute(builder: (_) => DetailsScreen(document))), //pass the product