Reputation: 1014
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
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