List screen to product details scree - flutter

I'm confused in this. I have created a screen in with list to products data is coming from an dummy API. no I have created the cards and I want to display product details in next screen. how can I show the same product details on second screen of pressed product.
I think we need to store index of api data in a variable somehow. this is the code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_get_api/model.dart';
import 'package:flutter_get_api/product_detail.dart';
import 'package:http/http.dart' as http;
class Details extends StatefulWidget {
Details({Key? key}) : super(key: key);
#override
State<Details> createState() => _DetailsState();
}
class _DetailsState extends State<Details> {
Future<Model> getProductsApi() async {
final responce =
await http.get(Uri.parse('https://dummyjson.com/products'));
var data = jsonDecode(responce.body.toString());
if (responce.statusCode == 200) {
return Model.fromJson(data);
} else {
return Model.fromJson(data);
}
}
var s = '\$';
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(),
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 32, 28, 80),
title: Text('Api Get'),
),
backgroundColor: Color.fromARGB(255, 32, 28, 80),
body: Column(
children: [
Expanded(
child: FutureBuilder<Model>(
future: getProductsApi(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.products!.length,
itemBuilder: (context, index) {
print(
snapshot.data!.products!.length,
);
return Column(
children: [
Padding(
padding: const EdgeInsets.all(5.0),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetails(),
));
},
child: Container(
height: 100,
width: 500,
child: Card(
color: Color.fromARGB(255, 185, 239, 243),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
10, 25, 10, 10),
child: CircleAvatar(
backgroundImage: NetworkImage(snapshot
.data!.products![index].thumbnail!
.toString()),
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.fromLTRB(
8, 10, 8, 0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Text(
snapshot
.data!.products![index].title
.toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17),
),
Text(
snapshot
.data!.products![index].brand
.toString(),
style: TextStyle(
fontWeight: FontWeight.bold),
),
Text(
snapshot.data!.products![index]
.description
.toString(),
),
],
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('\$' +
snapshot.data!.products![index].price
.toString()),
),
],
),
),
),
),

Pass your selected product to the ProductDetails constructor
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetails(snapshot.data!.products[index]),));
Watch the basics here: https://docs.flutter.dev/cookbook/navigation/passing-data

You can pass through constructor
class ProductDetails extends StatefulWidget {// can be StatelessWidget
final data; // better use DataType like `final ModeClass data
const ProductDetails({super.key, required this.data});
Now you can pass it like
builder: (context) => ProductDetails(snapshot.data!.products![index]),
Also you can pass with route arguments. Check more about navigation/passing-data

Related

type: 'Daftarangkot' is not a subtype of type 'DetailAngkot' in type cast

i am trying to make a list page get from api then want to show the details on the next page.
I have followed the tutorial from the following link https://docs.flutter.dev/cookbook/navigation/passing-data
when I click the detail page or the second page an error message appears "type: 'Daftarangkot' is not a subtype of type 'DetailAngkot' in type cast" on my emulator.
Below is first screen code.
import 'dart:ui';
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:kiriapp/angkottab/daftar.dart';
import 'package:kiriapp/angkottab/detailangkot.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
Future<List<Daftarangkot>> fetchData() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String? accessToken = sharedPreferences.getString("token");
String? idOwner = sharedPreferences.getString("id");
final response = await http.get(
Uri.parse(
"/api/angkot/find?owner_id=$idOwner"),
headers: {
'Authorization': 'Bearer $accessToken',
},
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
Map<String, dynamic> map = json.decode(response.body);
List<dynamic> jsonResponse = map["data"];
return jsonResponse.map((data) => new Daftarangkot.fromJson(data)).toList();
} else {
throw Exception('Eror Ketika Menampilkan! Diharap Login Ulang.');
}
}
class Daftarangkot {
final String id;
final String plat_nomor;
final String status;
final String pajak_tahunan;
Daftarangkot(
{required this.id,
required this.plat_nomor,
required this.status,
required this.pajak_tahunan});
factory Daftarangkot.fromJson(Map<String, dynamic> json) {
return Daftarangkot(
id: json['plat_nomor'],
plat_nomor: json['plat_nomor'],
status: json['status'],
pajak_tahunan: json['pajak_tahunan'],
);
}
}
class DetailAngkot {
final String detail_id;
final String detail_plat_nomor;
final String detail_pajak_tahunan;
final String detail_pajak_stnk;
final String detail_kir_bulanan;
final String detail_is_beroperasi;
final String detail_status;
const DetailAngkot(
this.detail_id,
this.detail_plat_nomor,
this.detail_pajak_tahunan,
this.detail_pajak_stnk,
this.detail_kir_bulanan,
this.detail_is_beroperasi,
this.detail_status,
);
}
class AngkotsScreen extends StatefulWidget {
const AngkotsScreen({Key? key, required this.angkots}) : super(key: key);
final List<DetailAngkot> angkots;
#override
State<AngkotsScreen> createState() => _AngkotsScreenState();
}
class _AngkotsScreenState extends State<AngkotsScreen> {
late Future<List<Daftarangkot>> futureData;
#override
void initState() {
super.initState();
futureData = fetchData();
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(right: 16, left: 16, top: 14),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FutureBuilder<List<Daftarangkot>>(
future: futureData,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Daftarangkot>? data = snapshot.data;
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: data?.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 8,
child: new InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detailangkot(),
settings: RouteSettings(
arguments: data![index],
),
));
},
child: Padding(
padding: const EdgeInsets.only(
left: 14, top: 12, bottom: 12),
child: Row(
children: [
Image.asset('assets/img/mobil.png'),
Padding(
padding: const EdgeInsets.only(
left: 14, right: 16),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text(data![index].plat_nomor,
style: TextStyle(
fontFamily: 'PoppinsBold',
fontSize: 24)),
Text(data[index].status,
style: TextStyle(
fontFamily: 'PoppinsReg',
fontSize: 18,
color:
Color(0xFF3FC100))),
Text(data[index].pajak_tahunan,
style: TextStyle(
fontFamily: 'PoppinsReg',
fontSize: 14)),
],
),
)
],
),
),
),
),
SizedBox(
height: 8,
),
],
);
});
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default show a loading spinner.
return Center(
child: CircularProgressIndicator(),
);
},
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => DaftarAngkot()));
},
backgroundColor: Color(0xff38AC00),
child: const Icon(
Icons.add,
color: Colors.white,
),
),
);
}
}
and this is the code of the second page or the detail page
import 'dart:ui';
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:kiriapp/BarChartSample1.dart';
import 'package:kiriapp/angkot.dart';
import 'package:kiriapp/home.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class Detailangkot extends StatefulWidget {
const Detailangkot({Key? key}) : super(key: key);
#override
State<Detailangkot> createState() => _DetailangkotState();
}
class _DetailangkotState extends State<Detailangkot> {
#override
Widget build(BuildContext context) {
final angkot = ModalRoute.of(context)!.settings.arguments as DetailAngkot;
// TODO: implement build
return Scaffold(
backgroundColor: Color(0xFFEFEFEF),
appBar: AppBar(
iconTheme: IconThemeData(
color: Colors.white, //change your color here
),
title: Text(
"Detail Angkot",
style: TextStyle(
fontFamily: 'PoppinsReg', fontSize: 24, color: Colors.white),
),
backgroundColor: Color(0xFF38AC00),
elevation: 0,
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 8,
),
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 8,
child: Padding(
padding: const EdgeInsets.only(left: 14, top: 12, bottom: 12),
child: Row(
children: [
Image.asset('assets/img/mobil.png'),
Padding(
padding: const EdgeInsets.only(left: 14, right: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(angkot.detail_plat_nomor,
style: TextStyle(
fontFamily: 'PoppinsBold', fontSize: 24)),
Text(angkot.detail_status,
style: TextStyle(
fontFamily: 'PoppinsReg',
fontSize: 18,
color: Color(0xFF3FC100))),
Row(
children: [
Text('Sopir ',
style: TextStyle(
fontFamily: 'PoppinsReg',
fontSize: 16,
color: Color(0xFF727272))),
Text('Rizky',
style: TextStyle(
fontFamily: 'PoppinsSemBold',
fontSize: 16,
color: Colors.black)),
],
)
],
),
)
],
),
),
),
],
),
),
),
);
}
}
Thanks
in here
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detailangkot(),
settings: RouteSettings(
arguments: data![index],
),
));
you are sending a Daftarangkot object
while here
final angkot = ModalRoute.of(context)!.settings.arguments as DetailAngkot;
you are expecting it as DetailAngkot. thus it throws this error.

How to Fix List Items are automatically changing their positing in flutter?

I am calling API data inside Listview. builder in flutter but the error I am facing is the items are changing their positions automatically.
For Example, When I load this class for the First Time the arrangement of List items is the same as required but after 30-40 seconds the List items arrangement automatically starts changing, and data showing itself randomly.
I am looking for someone who can help me to fix this issue?
For this purpose here is myClass Code.
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart'as HTTP;
import 'package:worldcup/utils/colors.dart';
class SeriesSchedulePage extends StatefulWidget {
#override
_SeriesSchedulePageState createState() => _SeriesSchedulePageState();
}
class _SeriesSchedulePageState extends State<SeriesSchedulePage> {
List<dynamic> matches = [];
var match;
getSchedule() async {
http.Response response = await http
.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
matches = parseData['matchList']["matches"];
setState(() {
match = matches;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.primaryWhite,
appBar: AppBar(
backgroundColor: AppColors.yellow,
elevation: 0,
centerTitle: true,
leading: IconButton(
onPressed: () {
Navigator.pop(context,true);
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
title: Text(
'Schedule',
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 17),
),
),
body: Container(
child: FutureBuilder(
future: getSchedule(),
builder: (context, snapshot) {
if (match == null) {
return Center(
child: CupertinoActivityIndicator(
animating: true, radius: 15));
} else
return ListView.builder(
itemCount: matches.length,
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
if (matches[index]["status"] =="UPCOMING") {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(left: 15, top: 7, bottom: 7, right: 15),
child: Row(
children: [
SizedBox(width: 20,),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
matches[index]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700, fontSize: 15),
),
SizedBox(height: 10,),
Text(
matches[index]["homeTeam"]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700, fontSize: 15),
),
SizedBox(height: 10,),
Text(
matches[index]["awayTeam"]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w500, fontSize: 13),
),
],
),
],
),
),
],
),
),
)
);
} else {
return Center(
child: Text("No Upcoming Match in this series"),
);
}
}
);
},
),
)
);
}
}
The issue is because getSchedule() has a setState inside it. When the build method is called, getSchedule() will trigger, and since it is calling setState , the build method is being called again, causing your widgets to continuously rebuild in an infinite loop.
What you need to do is prevent such a loop from happening. I see that you are using FutureBuilder too, that is a solution but your implementation is incorrect.
What you should do is this:
Future<List<dynamic>> getSchedule() async {
http.Response response =
await http.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
var matches = parseData['matchList']["matches"];
return matches;
}
This function returns a Future<List<dynamic>> which your future builder can use to handle the builds. For info on future builder here https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html.
Since you FutureBuilder will react to what is provided by getSchedule() when the future is complete, you do not need to use setState to rebuild.
I have modified your SeriesShedualPage here is the full code:
class SeriesSchedulePage extends StatefulWidget {
#override
_SeriesSchedulePageState createState() => _SeriesSchedulePageState();
}
class _SeriesSchedulePageState extends State<SeriesSchedulePage> {
Future<List<dynamic>> getSchedule() async {
http.Response response =
await http.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
var matches = parseData['matchList']["matches"];
return matches;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder<List<dynamic>>(
future: getSchedule(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<dynamic> matches = snapshot.data!;
return ListView.builder(
itemCount: matches.length,
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
if (matches[index]["status"] == "UPCOMING") {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(
left: 15, top: 7, bottom: 7, right: 15),
child: Row(
children: [
SizedBox(
width: 20,
),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
matches[index]['name'].toString(),
textScaleFactor: 0.9,
),
SizedBox(
height: 10,
),
Text(
matches[index]["homeTeam"]['name']
.toString(),
textScaleFactor: 0.9,
),
SizedBox(
height: 10,
),
Text(
matches[index]["awayTeam"]['name']
.toString(),
textScaleFactor: 0.9,
),
],
),
],
),
),
],
),
),
));
} else {
return Center(
child: Text("No Upcoming Match in this series"),
);
}
});
}
return Center(
child: CupertinoActivityIndicator(animating: true, radius: 15));
},
),
));
}
}

The method was called on null Flutter error

I have seen many people having this error in other StackOverflow posts but when I am struggling to implement the answers to other questions to my own code. The code being used is from the GitHub repository https://github.com/sbis04/events_demo.
This is how I call the method:
class _ThirdRoute extends State<ThirdRoute> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Calendar"),
),
body: Column(
children: <Widget>[
DashboardScreen(),
],
),
);
}
}
And this is the method in another .dart file:
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
Storage storage = Storage();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
iconTheme: IconThemeData(
color: Colors.grey, //change your color here
),
title: Text(
'Event Details',
style: TextStyle(
fontSize: 22,
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => CreateScreen(),
),
);
},
),
body: Padding(
padding: const EdgeInsets.only(
left: 16.0,
right: 16.0,
),
child: Container(
child: StreamBuilder(
stream: storage.retrieveEvents(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.data.documents.length > 0) {
return ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
Map<String, dynamic> eventInfo = snapshot.data.documents[index].data();
EventInfo event = EventInfo.fromMap(eventInfo);
DateTime startTime = DateTime.fromMillisecondsSinceEpoch(event.startTimeInEpoch);
DateTime endTime = DateTime.fromMillisecondsSinceEpoch(event.endTimeInEpoch);
String startTimeString = DateFormat.jm().format(startTime);
String endTimeString = DateFormat.jm().format(endTime);
String dateString = DateFormat.yMMMMd().format(startTime);
return Padding(
padding: EdgeInsets.only(bottom: 16.0),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => EditScreen(event: event),
),
);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.only(
bottom: 16.0,
top: 16.0,
left: 16.0,
right: 16.0,
),
= child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
Text(
event.description,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Text(
event.link,
),
),
SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 50,
width: 5,
),
SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
dateString,
),
Text(
'$startTimeString - $endTimeString',
),
],
)
],
),
],
),
),
],
),
),
);
},
);
} else {
return Center(
child: Text(
'No Events',
),
);
}
}
return Center(
child: CircularProgressIndicator(
strokeWidth: 2,
),
);
},
),
),
),
);
}
}
If anyone would be able to give me some advice on how to solve the error:
The method 'collection' was called on null. Receiver: null. Tried calling: collection("events"). The relevant error-causing widget was DashboardScreen
EDIT This is my storage.dart file as requested in the comments:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'calendar_client.dart';
final CollectionReference mainCollection = FirebaseFirestore.instance.collection('event');
final DocumentReference documentReference = mainCollection.doc('test');
class Storage {
Future<void> storeEventData(EventInfo eventInfo) async {
DocumentReference documentReferencer = documentReference.collection('events').doc(eventInfo.id);
Map<String, dynamic> data = eventInfo.toJson();
print('DATA:\n$data');
await documentReferencer.set(data).whenComplete(() {
print("Event added to the database, id: {${eventInfo.id}}");
}).catchError((e) => print(e));
}
Future<void> updateEventData(EventInfo eventInfo) async {
DocumentReference documentReferencer = documentReference.collection('events').doc(eventInfo.id);
Map<String, dynamic> data = eventInfo.toJson();
print('DATA:\n$data');
await documentReferencer.update(data).whenComplete(() {
print("Event updated in the database, id: {${eventInfo.id}}");
}).catchError((e) => print(e));
}
Future<void> deleteEvent({#required String id}) async {
DocumentReference documentReferencer = documentReference.collection('events').doc(id);
await documentReferencer.delete().catchError((e) => print(e));
print('Event deleted, id: $id');
}
Stream<QuerySnapshot> retrieveEvents() {
Stream<QuerySnapshot> myClasses = documentReference.collection('events').orderBy('start').snapshots();
return myClasses;
}
}

How to sent data into two different class within a file using navigator in flutter

I am lost my direction. Can Someone help me how can I send my data from the first page to the second page using Navigator? There are two types of class that exist in the destination file which are a stateful widget and a stateless widget. I am trying to send data from the first page using navigator:
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new restaurantLISTVIEW(category :categoriesList[index].name)));
The restaurantLISTVIEW is a stateful class on the second page. How can I share the data with the stateless class within the same file?
My full code on the first page:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:phpfood/restaurantlist.dart';
//import 'globals.dart' as globals;
import 'custom_textW.dart';
class Category {
final String name;
final String image;
Category({#required this.name, #required this.image});
}
List<Category> categoriesList = [
Category(name: "Breakfast", image: "nasilemak.png"),
//Category(name: "Kuih", image: "kuih.png"),
Category(name: "Lunch", image: "lunch.png"),
//Category(name: "Minum Petang", image: "mnmptg.png"),
Category(name: "Dinner", image: "mknmlm.png"),
//Category(name: "Minum Malam", image: "mnmmlm.png"),
//Category(name: "Minuman", image: "air.png"),
];
class Categories extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categoriesList.length,
itemBuilder: (_, index) {
return Padding(
padding: const EdgeInsets.only(left: 28.0, top: 8),
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(color: Colors.white, boxShadow: [
BoxShadow(
color: Colors.red[200], offset: Offset(4, 6), blurRadius: 20)
]),
//tambah di sini kalau nk gesture
child: InkWell(
//onTap: ()=> Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new SarapanPagi(),)),
onTap: (){
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new restaurantLISTVIEW(category :categoriesList[index].name)));
},
/*{
if(categoriesList[index].name == "Breakfast"){
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new restaurantLISTVIEW(category: 'breakfast')));
//Navigator.of(context).push(MaterialPageRoute<void>(builder: (context) => restaurantLISTVIEW(category: 'breakfast',),),);
}
else if(categoriesList[index].name == "Lunch"){
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new restaurantLISTVIEW()));
}
else if(categoriesList[index].name == "Dinner"){
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new restaurantLISTVIEW()));
}
},*/
child: Image.asset(
"images/${categoriesList[index].image}",
width: 100,
),
),
),
SizedBox(
height: 5,
),
CustomText(
text: categoriesList[index].name,
size: 17,
colors: Colors.black,
)
],
),
);
},
),
);
}
}
My full code on the second page:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'breakfast.dart';
// ignore: camel_case_types
class restaurantLISTVIEW extends StatefulWidget {
restaurantLISTVIEW({this.category});
final String category;
#override
_restaurantLISTVIEWState createState() => _restaurantLISTVIEWState();
}
// ignore: camel_case_types
class _restaurantLISTVIEWState extends State<restaurantLISTVIEW> {
Future<List> getData() async{
var url = 'http://10.0.2.2/foodsystem/restaurantlist.php';
var data = {'product_type': 'xde pape ppon saje nk hantar value'};
var response = await http.post(url, body: json.encode(data));
//final response= await http.get("http://10.0.2.2/foodsystem/getdata.php");
return json.decode(response.body);}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//Text("Restaurant's Owner Page"),
Text('${widget.category}', textAlign: TextAlign.center, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w700), ),
],
),
centerTitle: false,
//automaticallyImplyLeading: false,
),
body:
Padding(
padding: const EdgeInsets.only(bottom: 20, left: 5, right: 5),
child: Column(
children: [
SizedBox(height: 30,),
Container(
//decoration: BoxDecoration(border: Border.all(color: Colors.black, width: 4), borderRadius: BorderRadius.circular(15)),
height: 600,
child: FutureBuilder<List>(
future: getData(),
builder: (context, snapshot){
if(snapshot.hasError) print(snapshot.error);
return snapshot.hasData ?
ItemList(list: snapshot.data,) :
Center(child: CircularProgressIndicator(),);
},
),
),
FloatingActionButton(
onPressed: (){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(
'${widget.category}'
),
);
},
);
},
),
SizedBox(height: 10,),
],
),
),
);
}
}
class ItemList extends StatelessWidget {
final List list;
final String category;
ItemList({this.list, this.category});
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
//color: Colors.red.shade100,
height: 600,
child: ListView.builder(
itemCount: list==null ? 0 : list.length,
itemBuilder: (context, i){
return new Container(
height: 200,
child: new GestureDetector(
onTap: ()
{Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new SarapanPagi(list: list, index: i, category: category,)));},
/*{
if(category == "Breakfast"){
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new SarapanPagi(list: list, index: i, category: category,)));
}
},*/
child: new Card(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FloatingActionButton(
onPressed: (){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(
'$category hellp'
),
);
},
);
},
),
Row(
children: [
Container(
constraints: BoxConstraints(minWidth: 180, maxWidth: 180),
child:
Column(
children: [
Text(list[i]["restaurant_name"], style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), textAlign: TextAlign.center,),
Text("Restaurant ID: ${list[i]["restaurant_id"]}", style: TextStyle(fontSize: 20,), textAlign: TextAlign.center,),
],
),
),
Padding(
padding: const EdgeInsets.only(left :20.0),
child: Container(
constraints: BoxConstraints(minWidth: 150, maxWidth: 300),
child:
SizedBox(
width: 50,
child: Column(
children: [
Text("SSM: ${list[i]["restaurant_ssm"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 15),),
Text("Phone: ${list[i]["restaurant_phone"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 15),),
Text("Address: ${list[i]["restaurant_address"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 15),),
],
),
),
),
),
],
),
Row(
children: [
],
),
],
),
),
),
);
},
),
),
);
}
}
As you can see in the stateless class, I am already calling the value from the first page, but it returns null because there is nothing forwarded to that class.
The problem is that you did not share the name data for the ItemList class through the category parameter:
make the following correction:
builder: (context, snapshot){
if(snapshot.hasError) print(snapshot.error);
return snapshot.hasData ?
ItemList(list: snapshot.data, category: widget.category) :
Center(child: CircularProgressIndicator(),);
},
a tip is to use the #required notation in the widget constructor so as not to forget to fill in the named parameters. Example:
class ItemList extends StatelessWidget {
final List list;
final String category;
ItemList({#required this.list, #required this.category});
#override
Widget build(BuildContext context) {
return Container();
}
}

how to use widget value from stateful into stateless

I am having a stuck on transferring the value from the second page to the third page using the value pass from the first page. when I am trying to use the usual way that I am used to calling the data in the stateful widget, it returns an error on undefined.
class restaurantLISTVIEW extends StatefulWidget {
restaurantLISTVIEW({this.category});
final String category;
#override
_restaurantLISTVIEWState createState() => _restaurantLISTVIEWState();
}
within extends state:(working)
FloatingActionButton(
onPressed: (){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(
'${widget.category}'
),
);
},
);
},),
error on extends stateless widget, return null: (not working)
onTap: ()
{
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new SarapanPagi(list: list, index: i, category: category)));
}
within extends stateless:(not working)
FloatingActionButton(
onPressed: (){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(
'$category hellp'
),
);
},
);
},),
The whole code on the second page:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as HTTP;
import 'breakfast.dart';
// ignore: camel_case_types
class restaurantLISTVIEW extends StatefulWidget {
restaurantLISTVIEW({this.category});
final String category;
#override
_restaurantLISTVIEWState createState() => _restaurantLISTVIEWState();
}
// ignore: camel_case_types
class _restaurantLISTVIEWState extends State<restaurantLISTVIEW> {
Future<List> getData() async{
var url = 'http://10.0.2.2/foodsystem/restaurantlist.php';
var data = {'product_type': 'xde pape ppon saje nk hantar value'};
var response = await http.post(url, body: json.encode(data));
//final response= await http.get("http://10.0.2.2/foodsystem/getdata.php");
return json.decode(response.body);}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//Text("Restaurant's Owner Page"),
Text('${widget.category}', textAlign: TextAlign.center, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w700), ),
],
),
centerTitle: false,
//automaticallyImplyLeading: false,
),
body:
Padding(
padding: const EdgeInsets.only(bottom: 20, left: 5, right: 5),
child: Column(
children: [
SizedBox(height: 30,),
Container(
//decoration: BoxDecoration(border: Border.all(color: Colors.black, width: 4), borderRadius: BorderRadius.circular(15)),
height: 600,
child: FutureBuilder<List>(
future: getData(),
builder: (context, snapshot){
if(snapshot.hasError) print(snapshot.error);
return snapshot.hasData ?
ItemList(list: snapshot.data,) :
Center(child: CircularProgressIndicator(),);
},
),
),
FloatingActionButton(
onPressed: (){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(
'${widget.category}'
),
);
},
);
},
),
SizedBox(height: 10,),
],
),
),
);
}
}
class ItemList extends StatelessWidget {
final List list;
final String category;
ItemList({this.list, this.category});
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
//color: Colors.red.shade100,
height: 600,
child: ListView.builder(
itemCount: list==null ? 0 : list.length,
itemBuilder: (context, i){
return new Container(
height: 200,
child: new GestureDetector(
onTap: ()
{
if(widget.category == "Breakfast"){
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new SarapanPagi(list: list, index: i, category: category)));
}
},
child: new Card(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
constraints: BoxConstraints(minWidth: 180, maxWidth: 180),
child:
Column(
children: [
Text(list[i]["restaurant_name"], style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), textAlign: TextAlign.center,),
Text("Restaurant ID: ${list[i]["restaurant_id"]}", style: TextStyle(fontSize: 20,), textAlign: TextAlign.center,),
],
),
),
Padding(
padding: const EdgeInsets.only(left :20.0),
child: Container(
constraints: BoxConstraints(minWidth: 150, maxWidth: 300),
child:
SizedBox(
width: 50,
child: Column(
children: [
Text("SSM: ${list[i]["restaurant_ssm"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 15),),
Text("Phone: ${list[i]["restaurant_phone"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 15),),
Text("Address: ${list[i]["restaurant_address"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 15),),
],
),
),
),
),
],
),
Row(
children: [
],
),
],
),
),
),
);
},
),
),
);
The whole code on the third page:
import 'dart:convert';
import 'package:http/http.dart' as HTTP;
import 'package:flutter/material.dart';
//import 'globals.dart' as globals;
class SarapanPagi extends StatefulWidget {
final List list;
final int index;
final String category;
SarapanPagi({this.index,this.list,this.category});
#override
_SarapanPagiState createState() => _SarapanPagiState();
}
class _SarapanPagiState extends State<SarapanPagi> {
Future<List> getData() async{
var url = 'http://10.0.2.2/foodsystem/breakfastlist.php';
var data = {
'product_type': 'Breakfast',
'product_owner': widget.list[widget.index]['restaurant_id'],
};
var response = await http.post(url, body: json.encode(data));
//final response= await http.get("http://10.0.2.2/foodsystem/getdata.php");
return json.decode(response.body);}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
//Text("Restaurant's Owner Page"),
Text(widget.list[widget.index]['restaurant_name'], textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.w700), ),
],
),
centerTitle: false,
//automaticallyImplyLeading: false,
),
body:
Padding(
padding: const EdgeInsets.only(bottom: 20, left: 5, right: 5),
child: Column(
children: [
SizedBox(height: 30,),
Container(
//decoration: BoxDecoration(border: Border.all(color: Colors.black, width: 4), borderRadius: BorderRadius.circular(15)),
height: 600,
child: FutureBuilder<List>(
future: getData(),
builder: (context, snapshot){
if(snapshot.hasError) print(snapshot.error);
return snapshot.hasData ?
ItemList(list: snapshot.data,) :
Center(child: CircularProgressIndicator(),);
},
),
),
SizedBox(height: 10,),
],
),
),
);
}
}
class ItemList extends StatelessWidget {
final List list;
ItemList({this.list});
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
//color: Colors.red.shade100,
height: 600,
child: ListView.builder(
itemCount: list==null ? 0 : list.length,
itemBuilder: (context, i){
return new Container(
height: 200,
child: new GestureDetector(
onTap: (){},
child: new Card(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
"images/${list[i]['image']}",
width: 150,
height: 150,
),
),
Padding(
padding: const EdgeInsets.only(left: 20.0, bottom: 0),
child:
Column(
children: [
Text(list[i]["product_name"], textAlign: TextAlign.center, style: TextStyle(fontSize: 30),),
Text("Price RM : ${list[i]["product_price"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 25),),
RaisedButton(
shape: RoundedRectangleBorder(borderRadius: new BorderRadius.circular(40.0)),
color: Colors.red.shade300,
child: Text("Add to Cart", style: TextStyle(fontWeight: FontWeight.bold),),
onPressed: (){},
)
],
),
),
],
),
/*ListTile(
title: Text(list[i]["product_name"], textAlign: TextAlign.center, style: TextStyle(fontSize: 30),),
leading:
Image.asset(
"images/${list[i]['image']}",
width: 100,
height: 100,
),
subtitle: Text("Price RM : ${list[i]["product_price"]}", textAlign: TextAlign.center, style: TextStyle(fontSize: 25),),
),*/
],
),
),
),
);
},
),
),
);
The
You are not using widget.category in restaurantLISTVIEW page but in ItemList widget, that's why you are getting that error.
Adjust your ItemList widget like this
class ItemList extends StatelessWidget {
final List list;
final String category;
ItemList({this.list, this.category});
}
So, your navigation line in ItemList must be
Navigator.of(context).push(new MaterialPageRoute(builder: (BuildContext context)=> new SarapanPagi(list: list, index: i, category: category)));
Also, in SarapanPagi page the variable type of category is not int by String
You are not using widget.category in restaurantLISTVIEW page but in ItemList widget,
The solution that I made is:
this code on the stateful widget class for the second page, needs to be improved by adding the value of the category.
ItemList(list: snapshot.data,)
improved code:
this code forwards the value store in the widget category to the second page from the stateful widget into stateless widget.
ItemList(list: snapshot.data,category: widget.category) :