Part_Time_Nerd
Part_Time_Nerd

Reputation: 1014

How do I pass a single Firestore document ID to another class based on a selection using Flutter/Dart?

I am trying to design a feature using flutter that when a user selects a thumbnail image of a trip it will take the user to a page that has more details of the trip they selected. I am trying to query the Firestore db as little as possible so I was trying to get the document ID from a single query snapshot and pass it to the IndividualTripPackage class. I have tried this approach numerous ways but all of them have failed. I alsow looked at other solutions people posted on SO and I could not get them to work for my specific case. What am I doing wrong? I am new to flutter so if you have ideas about other approaches or more efficient solutions I am open to suggestions.

TripPackages Class:

class _TripPackagesState extends State<TripPackages> {
  @override
  Widget build(BuildContext context) {
 //Some other code......
            child: SingleChildScrollView(
              child: StreamBuilder<QuerySnapshot>(
                stream:
                    Firestore.instance.collection('trip_package').snapshots(),
                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> docSnapshot) {
                  if (!docSnapshot.hasData) return const Text('Loading...');
                  final int docCount = docSnapshot.data.documents.length;
                  return GridView.builder(
                    shrinkWrap: true,
                    primary: false,
                    scrollDirection: Axis.vertical,
                    itemCount: docCount,
                    itemBuilder: (_, int index) {
                      DocumentSnapshot document =
                          docSnapshot.data.documents[index];
                      return GestureDetector(
                        onTap: () => Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (_) => IndividualTripPackage(
                                docID: docSnapshot.data.documents[index]),
                          ),
    //Some other code .....
  }
}

IndividualTripPackage Class:

class IndividualTripPackage extends StatefulWidget {
  DocumentSnapshot docID;
  IndividualTripPackage({this.docID});
  @override
  _IndividualTripPackageState createState() => _IndividualTripPackageState();
}

class _IndividualTripPackageState extends State<IndividualTripPackage> {
  @override
  Widget build(BuildContext context) {
    final String docID = widget.docID.data['docID'];
    return Material(
      child: SafeArea(
        child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints viewportConstraints) {
            return SingleChildScrollView(
              child: ConstrainedBox(
                constraints: BoxConstraints(minHeight: viewportConstraints.maxHeight),
                child: StreamBuilder(
                    stream: Firestore.instance.collection('trip_package').document('docID').snapshots(),
                    builder: (context, snapshot) {
                      if (!snapshot.hasData) {
                        return Text('Loading data....Please wait...');
                      } else {
                        final int itemCount = snapshot.data.document('docID').data['itineraryItems'].length;
                        return Column(...);
                      }
                    }),
      //Some more code........
  }
}

Upvotes: 2

Views: 1167

Answers (1)

Will Hlas
Will Hlas

Reputation: 1351

Alrighty I'm hoping this answers your question!

I've been using a method like this for my app and it seems to work for me. Of course you will want to adjust the class names and other code to your liking, but hopefully this is what you're trying to do.

Trip Thumbnail

import 'package:flutter/material.dart';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:my_test_project/screens/detail.dart';

class Thumbnail extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ThumbnailState();
}

class _ThumbnailState extends State<Thumbnail> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Text(
          'Thumbnail'
        ),
      ),
      body: ListView(
        children: <Widget>[
          StreamBuilder<QuerySnapshot>(
            stream: Firestore.instance.collection('trips').snapshots(),
            builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (snapshot.hasError) return Text('Error: ${snapshot.error}');
              if (!snapshot.hasData) return Container(
                child: Center(
                  child: CircularProgressIndicator()
                ),
              );
              return Column(
                children: snapshot.data.documents.map((doc) {
                  return GestureDetector(
                    onTap: () {
                      var docId = doc.documentID;
                      Navigator.push(context, MaterialPageRoute(builder: (context) => Detail(docId)));
                    },
                    child: Container(
                      child: Image(
                        image: NetworkImage(
                          doc.data['photo']
                        ),
                      ),
                    ),
                  );
                }).toList(),
              );
            },
          )
        ],
      )
    );
  }
}

Trip Detail

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class Detail extends StatefulWidget {

  final docId;
  Detail(this.docId);

  @override
  State<StatefulWidget> createState() => _DetailState(docId);
}

class _DetailState extends State<Detail> {

  final docId;
  _DetailState(this.docId);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Detail'
        ),
      ),
      body: ListView(
        children: <Widget>[
          StreamBuilder<DocumentSnapshot>(
            stream: Firestore.instance.collection('trips').document(docId).snapshots(),
            builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
              if (snapshot.hasError) return Text('Error: ${snapshot.error}');
              if (!snapshot.hasData) return Container(
                child: Center(
                  child: CircularProgressIndicator()
                ),
              );
              return Column(
                children: <Widget>[
                  Container(
                    child: Text(
                      snapshot.data['title'],
                      style: TextStyle(
                        fontSize: 24.0
                      ),
                    ),
                  ),
                  Container(
                    child: Image(
                      image: NetworkImage(
                        snapshot.data['photo']
                      ),
                    ),
                  ),
                  Container(
                    child: Text(
                      snapshot.data['body']
                    )
                  )
                ],
              );
            },
          )
        ],
      ),
    );
  }
}

Basically I'm passing along a variable to the next screen that has the document's ID to use for the DocumentSnapshot Stream.

Upvotes: 5

Related Questions