type '(dynamic) => ProductDetailsModel' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform' - Flutter - flutter

Help me please, How can I get this data in single page. When I trying to fetch data from api I get this error :
type '(dynamic) => ProductDetailsModel' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform' - Flutter.
I need to just show data in single page. I am trying to get data with Future Builder not get.
This is my onTap:
onTap: () {singleProductDataC.getSingleProductData(
productId: item.id,
productSlug: item.slug,
);
.
This Is My Api :
{
"productdetails": {
"id": 1,
"proCategory": "1",
"proSubcategory": "1",
"proChildCategory": "1",
"proBrand": null,
"proShop": null,
"proName": "Nestle LACTOGEN 1 Infant Formula With Iron TIN",
"slug": "nestle-lactogen-1-infant-formula-with-iron-tin",
"proPurchaseprice": "550",
"proOldprice": "750",
"proNewprice": "630",
"proCode": null,
"proLimit": null,
"proDescription": "<ul><li> is a super quality online super shop that, at this moment has service in Dhaka city. ",
"proQuantity": "12",
"aditionalshipping": null,
"combo": null,
"offer": null,
"video": null,
"unit": "400 gm",
"deliveryarea": null,
"homedelivery": null,
"returnwarranty": null,
"codavailable": null,
"warranty": null,
"proLocation": "1",
"ratting": "12.1",
"status": "1",
"created_at": "2022-01-01T20:51:03.000000Z",
"updated_at": "2022-02-12T05:58:43.000000Z",
"reviews_count": "3",
"category": {
"id": 1,
"name": "Fruits & Vegetables",
"slug": "fruits--vegetables",
"image": "public/uploads/category/1642326298-fruits-and-vegetables.png",
"frontProduct": "1",
"level": null,
"status": "1",
"created_at": "2022-01-01T18:15:36.000000Z",
"updated_at": "2022-01-15T22:44:58.000000Z"
},
"brand": null
},
"images": [
{
"id": 6,
"product_id": "1",
"image": "public/uploads/product/1644645523-1644066476-0129980_khusboo-premium-olive-pickles-400-gm.jpeg",
"created_at": "2022-02-12T05:58:43.000000Z",
"updated_at": "2022-02-12T05:58:43.000000Z"
}
]
}
This Is My Controller
import 'package:Darucheeni/src/configs/appConfigs.dart';
import 'package:Darucheeni/src/pages/productPage/productDetailsPage.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart';
class ProductDetailsController extends GetxController {
final dio = Dio();
final singleProductsList = RxList<ProductDetailsModel>();
getSingleProductData({
String? productSlug,
int? productId,
}) async {
final res = await dio.get(
baseUrl + 'product-details/$productId/$productSlug',
);
final List<ProductDetailsModel> productDetaisData = res
.data['productdetails']
.map((json) => ProductDetailsModel.fromJson(json))
.toList()
.cast<ProductDetailsModel>();
print('------------------------------>');
print('Status Code : ${res.statusCode}');
print('Headers : ${res.headers}');
print('realUri : ${res.realUri}');
print('statusMessage : ${res.statusMessage}');
print('requestOptions : ${res.requestOptions}');
print(res.data['productdetails']);
print('------------------------------>');
await Get.to(ProductDetailsPage());
print(res.data);
if (res.statusCode == 200) {
print(productDetaisData);
singleProductsList.addAll((res.data as List)
.map((e) => ProductDetailsModel.fromJson(e))
.toList());
}
}
}
This Is My Details Page :
import 'package:Darucheeni/src/LottieAnimation/loadingLottie.dart';
import 'package:Darucheeni/src/controllers/mainController/baseController.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:Darucheeni/src/configs/appColors.dart';
import 'package:Darucheeni/src/widgets/textWidget/kText.dart';
import '../../configs/appConfigs.dart';
import '../../configs/iconAndImages.dart';
import '../../widgets/QuantityWidget/quantityWidgets.dart';
import '../../widgets/button/customBackButton.dart';
class ProductDetailsPage extends StatefulWidget with BaseController {
// final int? productId;
// final String? productSlug;
// ProductDetailsPage({
// this.productId,
// this.productSlug,
// });
#override
State<ProductDetailsPage> createState() => _ProductDetailsPageState();
}
class _ProductDetailsPageState extends State<ProductDetailsPage>
with BaseController {
bool isAddtoBag = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
leading: customBackButton(),
title: KText(
text: 'Product Details',
fontSize: 25,
color: black,
fontWeight: FontWeight.w500,
fontFamily: brushScriptFonts,
),
),
body: ListView(
children: [
// future builder give me some error
// FutureBuilder<Map<String, dynamic>>(
// future: singleProductDataC.getSingleProductData(),
// builder: ((context, snapshot) {
// print('-----------------------> ${snapshot.data}');
// if (!snapshot.hasData) {
// return LoadingLottie();
// }
// final products = snapshot.data!;
// print('-----------------------> $products');
// return Column(
// children: [
// Stack(
// children: [
// // Container(
// // color: white,
// // height: 250,
// // width: Get.width,
// // child: CachedNetworkImageWidget(
// // imageUrl: products!.imagesModel!.image.toString(),
// // ),
// // ),
// Positioned(
// top: 30,
// child: Image.asset(
// discountArrow,
// scale: 2,
// ),
// ),
// Positioned(
// top: 30,
// child: KText(
// text: ' -10%',
// color: white,
// fontSize: 16,
// fontWeight: FontWeight.bold,
// ),
// ),
// ],
// ),
// sizeH20,
// Padding(
// padding: paddingHori20,
// child: KText(
// text: products['proName'],
// fontSize: 25,
// color: black,
// maxLines: 100,
// fontFamily: segoeBoldFonts,
// ),
// ),
// sizeH20,
// sizeH20,
// Padding(
// padding: paddingHori20,
// child: Row(
// children: [
// KText(
// text: '৳ ',
// fontSize: 25,
// ),
// KText(
// text: products['proNewprice'],
// fontSize: 30,
// fontWeight: FontWeight.bold,
// ),
// sizeW20,
// KText(
// text: '৳ ${products['proOldprice']}',
// fontSize: 25,
// color: black54,
// decoration: TextDecoration.lineThrough,
// fontWeight: FontWeight.bold,
// ),
// Spacer(),
// KText(
// text: 'Unit : ',
// fontSize: 18,
// color: black,
// fontWeight: FontWeight.bold,
// ),
// KText(
// text: products['unit'],
// fontSize: 22,
// fontWeight: FontWeight.bold,
// ),
// ],
// ),
// ),
// sizeH20,
// sizeH20,
// Row(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// isAddtoBag == false
// ? InkWell(
// onTap: () {
// setState(() {
// isAddtoBag = true;
// });
// },
// child: Padding(
// padding: EdgeInsets.symmetric(horizontal: 60),
// child: Container(
// alignment: Alignment.center,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(30),
// color: white,
// ),
// child: Padding(
// padding: EdgeInsets.all(4),
// child: Container(
// alignment: Alignment.center,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(30),
// color: orange,
// ),
// child: Padding(
// padding: EdgeInsets.symmetric(
// horizontal: 30,
// vertical: 7,
// ),
// child: KText(
// text: 'Add To Bag',
// fontSize: 27,
// fontWeight: FontWeight.bold,
// color: white,
// ),
// ),
// ),
// ),
// ),
// ),
// )
// : QuantityWidget(
// iconSize: 30,
// cirecleRadius: 20,
// iconRadius: 16,
// quantityCSize: 25,
// circleColor: backgroundColor,
// ),
// ],
// ),
// sizeH10,
// Padding(
// padding: EdgeInsets.symmetric(horizontal: 10),
// child: Divider(
// color: orange,
// height: 30,
// ),
// ),
// sizeH10,
// Padding(
// padding: paddingHori20,
// child: KText(
// text: products['proName'],
// color: Colors.black45,
// fontSize: 20,
// maxLines: 100,
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// );
// }),
// ),
ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: singleProductDataC.singleProductsList.length,
itemBuilder: (context, index) {
final products = singleProductDataC.singleProductsList[index].productdetails;
print(products);
return Column(
children: [
Stack(
children: [
// Container(
// color: white,
// height: 250,
// width: Get.width,
// child: CachedNetworkImageWidget(
// imageUrl: products!.imagesModel!.image.toString(),
// ),
// ),
Positioned(
top: 30,
child: Image.asset(
discountArrow,
scale: 2,
),
),
Positioned(
top: 30,
child: KText(
text: ' -10%',
color: white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
sizeH20,
Padding(
padding: paddingHori20,
child: KText(
text: products! .proName.toString(),
fontSize: 25,
color: black,
maxLines: 100,
fontFamily: segoeBoldFonts,
),
),
sizeH20,
sizeH20,
Padding(
padding: paddingHori20,
child: Row(
children: [
KText(
text: '৳ ',
fontSize: 25,
),
KText(
text: products.proNewprice.toString(),
fontSize: 30,
fontWeight: FontWeight.bold,
),
sizeW20,
KText(
text:
'৳ ${products .proOldprice.toString()}',
fontSize: 25,
color: black54,
decoration: TextDecoration.lineThrough,
fontWeight: FontWeight.bold,
),
Spacer(),
KText(
text: 'Unit : ',
fontSize: 18,
color: black,
fontWeight: FontWeight.bold,
),
KText(
text: products .unit.toString(),
fontSize: 22,
fontWeight: FontWeight.bold,
),
],
),
),
sizeH20,
sizeH20,
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
isAddtoBag == false
? InkWell(
onTap: () {
setState(() {
isAddtoBag = true;
});
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 60),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: white,
),
child: Padding(
padding: EdgeInsets.all(4),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(30),
color: orange,
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 30,
vertical: 7,
),
child: KText(
text: 'Add To Bag',
fontSize: 27,
fontWeight: FontWeight.bold,
color: white,
),
),
),
),
),
),
)
: QuantityWidget(
iconSize: 30,
cirecleRadius: 20,
iconRadius: 16,
quantityCSize: 25,
circleColor: backgroundColor,
),
],
),
sizeH10,
Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Divider(
color: orange,
height: 30,
),
),
sizeH10,
Padding(
padding: paddingHori20,
child: KText(
text: products .proName.toString(),
color: Colors.black45,
fontSize: 20,
maxLines: 100,
fontWeight: FontWeight.w500,
),
),
],
);
}),
sizeH20,
TextButton(
onPressed: () => Get.back(),
child: KText(
text: 'close',
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
sizeH20,
],
),
);
}
}
This Is My Model Class:
// ignore_for_file: unused_field
class ProductDetailsModel {
Productdetails? productdetails;
List<Images>? images;
ProductDetailsModel({this.productdetails, this.images});
ProductDetailsModel.fromJson(Map<String, dynamic> json) {
productdetails = json['productdetails'] != null
? new Productdetails.fromJson(json['productdetails'])
: null;
if (json['images'] != String) {
images = <Images>[];
json['images'].forEach((v) {
images!.add(new Images.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.productdetails != null) {
data['productdetails'] = this.productdetails!.toJson();
}
if (this.images != null) {
data['images'] = this.images!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Productdetails {
int? id;
String? proCategory;
String? proSubcategory;
String? proChildCategory;
String? proBrand;
String? proShop;
String? proName;
String? slug;
String? proPurchaseprice;
String? proOldprice;
String? proNewprice;
String? proCode;
String? proLimit;
String? proDescription;
String? shortDescription;
String? proQuantity;
String? aditionalshipping;
String? combo;
String? offer;
String? video;
String? unit;
String? deliveryarea;
String? homedelivery;
String? returnwarranty;
String? codavailable;
String? warranty;
String? proLocation;
String? ratting;
String? status;
String? createdAt;
String? updatedAt;
String? reviewsCount;
Category? category;
String? brand;
Productdetails(
{this.id,
this.proCategory,
this.proSubcategory,
this.proChildCategory,
this.proBrand,
this.proShop,
this.proName,
this.slug,
this.proPurchaseprice,
this.proOldprice,
this.proNewprice,
this.proCode,
this.proLimit,
this.proDescription,
this.shortDescription,
this.proQuantity,
this.aditionalshipping,
this.combo,
this.offer,
this.video,
this.unit,
this.deliveryarea,
this.homedelivery,
this.returnwarranty,
this.codavailable,
this.warranty,
this.proLocation,
this.ratting,
this.status,
this.createdAt,
this.updatedAt,
this.reviewsCount,
this.category,
this.brand, });
Productdetails.fromJson(Map<String, dynamic> json) {
id = json['id'];
proCategory = json['proCategory'];
proSubcategory = json['proSubcategory'];
proChildCategory = json['proChildCategory'];
proBrand = json['proBrand'];
proShop = json['proShop'];
proName = json['proName'];
slug = json['slug'];
proPurchaseprice = json['proPurchaseprice'];
proOldprice = json['proOldprice'];
proNewprice = json['proNewprice'];
proCode = json['proCode'];
proLimit = json['proLimit'];
proDescription = json['proDescription'];
shortDescription = json['shortDescription'];
proQuantity = json['proQuantity'];
aditionalshipping = json['aditionalshipping'];
combo = json['combo'];
offer = json['offer'];
video = json['video'];
unit = json['unit'];
deliveryarea = json['deliveryarea'];
homedelivery = json['homedelivery'];
returnwarranty = json['returnwarranty'];
codavailable = json['codavailable'];
warranty = json['warranty'];
proLocation = json['proLocation'];
ratting = json['ratting'];
status = json['status'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
reviewsCount = json['reviews_count'];
category = json['category'] != null
? new Category.fromJson(json['category'])
: null;
brand = json['brand'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['proCategory'] = this.proCategory;
data['proSubcategory'] = this.proSubcategory;
data['proChildCategory'] = this.proChildCategory;
data['proBrand'] = this.proBrand;
data['proShop'] = this.proShop;
data['proName'] = this.proName;
data['slug'] = this.slug;
data['proPurchaseprice'] = this.proPurchaseprice;
data['proOldprice'] = this.proOldprice;
data['proNewprice'] = this.proNewprice;
data['proCode'] = this.proCode;
data['proLimit'] = this.proLimit;
data['proDescription'] = this.proDescription;
data['shortDescription'] = this.shortDescription;
data['proQuantity'] = this.proQuantity;
data['aditionalshipping'] = this.aditionalshipping;
data['combo'] = this.combo;
data['offer'] = this.offer;
data['video'] = this.video;
data['unit'] = this.unit;
data['deliveryarea'] = this.deliveryarea;
data['homedelivery'] = this.homedelivery;
data['returnwarranty'] = this.returnwarranty;
data['codavailable'] = this.codavailable;
data['warranty'] = this.warranty;
data['proLocation'] = this.proLocation;
data['ratting'] = this.ratting;
data['status'] = this.status;
data['created_at'] = this.createdAt;
data['updated_at'] = this.updatedAt;
data['reviews_count'] = this.reviewsCount;
if (this.category != null) {
data['category'] = this.category!.toJson();
}
data['brand'] = this.brand;
return data;
}
}
class Category {
int? id;
String? name;
String? slug;
String? image;
String? frontProduct;
String? level;
String? status;
String? createdAt;
String? updatedAt;
Category(
{this.id,
this.name,
this.slug,
this.image,
this.frontProduct,
this.level,
this.status,
this.createdAt,
this.updatedAt});
Category.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
slug = json['slug'];
image = json['image'];
frontProduct = json['frontProduct'];
level = json['level'];
status = json['status'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['slug'] = this.slug;
data['image'] = this.image;
data['frontProduct'] = this.frontProduct;
data['level'] = this.level;
data['status'] = this.status;
data['created_at'] = this.createdAt;
data['updated_at'] = this.updatedAt;
return data;
}
}
class Images {
int? id;
String? productId;
String? image;
String? createdAt;
String? updatedAt;
Images({this.id, this.productId, this.image, this.createdAt, this.updatedAt});
Images.fromJson(Map<String, dynamic> json) {
id = json['id'];
productId = json['product_id'];
image = json['image'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['product_id'] = this.productId;
data['image'] = this.image;
data['created_at'] = this.createdAt;
data['updated_at'] = this.updatedAt;
return data;
}
}

Related

Null Check operator used on a null value

when click the showModalBottomSheet it's show on the screen
Null Check operator used on a null value
can anyone help to figure out which is the code error? kindly refer full code as below, TQ!
class ProductContentFirst extends StatefulWidget {
final List _productContentList;
const ProductContentFirst(this._productContentList, {Key? key})
: super(key: key);
#override
State<ProductContentFirst> createState() => _ProductContentFirstState();
}
class _ProductContentFirstState extends State<ProductContentFirst> {
ProductContentItem? _productContent;
List _attr = [];
#override
void initState() {
super.initState();
_productContent = widget._productContentList[0];
this._attr = this._productContent!.attr!;
//print(this._attr);
}
List<Widget>? _getAttrItemWidget(attrItem) {
List<Widget> attrItemList = [];
attrItem.list.forEach((item) {
attrItemList.add(Container(
margin: EdgeInsets.all(5),
child: Chip(
label: Text("${item}"),
padding: EdgeInsets.all(10),
),
));
print (item);
});
}
List<Widget>? _getAttrWidget() {
List<Widget> attrList = [];
this._attr.forEach((attrItem) {
attrList.add(Wrap(
children: [
Container(
width: ScreenAdapter.width(80.0),
child: Padding(
padding: EdgeInsets.only(top: ScreenAdapter.height(30.0)),
child: Text(
"${attrItem.cate}",
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
Container(
width: ScreenAdapter.width(600.0),
child: Wrap(
//children: [],
children: _getAttrItemWidget(attrItem)!,
),
)
],
));
print(attrItem.cate);
});
//return null;
}
_attrBottomSheet() {
showModalBottomSheet(
context: context,
builder: (context) {
return GestureDetector(
onTap: () {
false;
},
child: Stack(
children: [
Container(
padding: EdgeInsets.all(10),
child: ListView(
children: [
Column(
children: _getAttrWidget()!,
)
],
),
),
Positioned(
bottom: 0,
width: ScreenAdapter.width(750.0),
height: ScreenAdapter.height(100),
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
child: JdButton(
color: Color.fromRGBO(253, 1, 0, 0.9),
text: "Add Cart",
cb: () {
print("Add Cart");
},
),
)),
Expanded(
flex: 1,
child: Container(
child: JdButton(
color: Color.fromRGBO(255, 165, 0, 0.9),
text: "Buy",
cb: () {
print("Buy");
},
),
)),
],
))
],
),
);
});
}
#override
Widget build(BuildContext context) {
String pic = Config.domain + this._productContent!.pic!;
pic = pic.replaceAll("\\", "/");
return Container(
padding: EdgeInsets.all(10.0),
child: ListView(
children: [
AspectRatio(
aspectRatio: 16 / 12,
child: Image.network(
"${pic}",
fit: BoxFit.cover,
),
),
Container(
padding: EdgeInsets.only(top: 7),
child: Text(
"${this._productContent!.title}",
style: TextStyle(
color: Colors.black87, fontSize: ScreenAdapter.size(36)),
),
),
Container(
padding: EdgeInsets.only(top: 7),
child: Text(
"${this._productContent!.subTitle}",
style: TextStyle(
color: Colors.black54, fontSize: ScreenAdapter.size(28)),
),
),
Container(
padding: EdgeInsets.only(top: 7),
child: Row(
children: [
Expanded(
flex: 1,
child: Row(
children: [
Text("Price: "),
Text(
"${this._productContent!.price}",
style: TextStyle(
color: Colors.red,
fontSize: ScreenAdapter.size(46)),
)
],
),
),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("Old Price: "),
Text(
"${this._productContent!.oldPrice}",
style: TextStyle(
color: Colors.black38,
fontSize: ScreenAdapter.size(32),
decoration: TextDecoration.lineThrough),
),
],
),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 7),
height: ScreenAdapter.height(80.0),
child: InkWell(
onTap: () {
_attrBottomSheet();
},
child: Row(
children: [
Text(
"Select:",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text("115, Black, XL, 1 pcs")
],
),
),
),
Divider(),
Container(
height: ScreenAdapter.height(80.0),
child: Row(
children: [
Text(
"Delivery Fees:",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text("Free Delivery")
],
),
),
Divider(),
],
),
);
}
}
class ProductContentModel {
ProductContentItem? result;
ProductContentModel({this.result});
ProductContentModel.fromJson(Map<String, dynamic> json) {
result = json['result'] != null
? new ProductContentItem.fromJson(json['result'])
: null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.result != null) {
data['result'] = this.result!.toJson();
}
return data;
}
}
class ProductContentItem {
String? sId;
String? title;
String? cid;
Object? price;
String? oldPrice;
Object? isBest;
Object? isHot;
Object? isNew;
String? status;
String? pic;
String? content;
String? cname;
List<Attr>? attr;
String? subTitle;
Object? salecount;
ProductContentItem(
{this.sId,
this.title,
this.cid,
this.price,
this.oldPrice,
this.isBest,
this.isHot,
this.isNew,
this.status,
this.pic,
this.content,
this.cname,
this.attr,
this.subTitle,
this.salecount});
ProductContentItem.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
title = json['title'];
cid = json['cid'];
price = json['price'];
oldPrice = json['old_price'];
isBest = json['is_best'];
isHot = json['is_hot'];
isNew = json['is_new'];
status = json['status'];
pic = json['pic'];
content = json['content'];
cname = json['cname'];
if (json['attr'] != null) {
attr = <Attr>[];
json['attr'].forEach((v) {
attr!.add(new Attr.fromJson(v));
});
}
subTitle = json['sub_title'];
salecount = json['salecount'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['_id'] = this.sId;
data['title'] = this.title;
data['cid'] = this.cid;
data['price'] = this.price;
data['old_price'] = this.oldPrice;
data['is_best'] = this.isBest;
data['is_hot'] = this.isHot;
data['is_new'] = this.isNew;
data['status'] = this.status;
data['pic'] = this.pic;
data['content'] = this.content;
data['cname'] = this.cname;
if (this.attr != null) {
data['attr'] = this.attr!.map((v) => v.toJson()).toList();
}
data['sub_title'] = this.subTitle;
data['salecount'] = this.salecount;
return data;
}
}
class Attr {
String? cate;
List<String>? list;
Attr({this.cate, this.list});
Attr.fromJson(Map<String, dynamic> json) {
cate = json['cate'];
list = json['list'].cast<String>();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['cate'] = this.cate;
data['list'] = this.list;
return data;
}
}
When the exception was thrown, this was the stack:
\#0 \_ProductContentFirstState.\_getAttrWidget.\<anonymous closure (package:flutter_jdshop/pages/ProductContent/ProductContentFirst.dart:64:54)
Don't use ! without checking null. While the snippet is large, follow these steps.
Check null, and then perform operation the place you've used !. It will be like if(result!=null)result.add(new FocusItemModel.fromJson(v));
the children can be children: _getAttrItemWidget(attrItem)??[]
You aren't returning widgets from _getAttrItemWidget and others. It will be
List<Widget> _getAttrItemWidget(attrItem) { // no need to return null
List<Widget> attrItemList = [];
attrItem.list.forEach((item) {
....
print (item);
});
return attrItemList;
}
In short Don't use ! without checking null. or provide default value on null case.
Find more about null-safety.

How to fetch data from REST API and display on Listview, Flutter

I am fairly new to using REST API to GET data and display in a Listview in Flutter. I have since been working on something like this, But i get Lost along the line. Hence I need Help with this.
My code Goes thus
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class TransactionDetails {
final String avatar;
final String name;
final String date;
final String amount;
TransactionDetails({required this.avatar, required this.name, required this.date, required this.amount});
factory TransactionDetails.fromJson(Map<String, dynamic> json) {
return TransactionDetails(
avatar: json['avatar'],
name: json['name'],
date: json['date'],
amount: json['amount']);
}
}
class BaseScreen extends StatelessWidget {
const BaseScreen({Key? key}) : super(key: key);
Future<TransactionDetails> fetchTransaction() async {
final response = await http
.get('https://brotherlike-navies.000webhostapp.com/people/people.php');
if (response.statusCode == 200) {
return TransactionDetails.fromJson(json.decode(response.body));
} else {
throw Exception('Request Failed.');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: double.infinity,
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
margin: const EdgeInsets.all(15),
width: 319,
height: 100,
color: Colors.green,
alignment: Alignment.center,
child: const Text(
'\$5200.00',
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(15),
width: 319,
height: 100,
color: Colors.green,
alignment: Alignment.center,
child: const Text(
'\$1200.00',
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
SizedBox(height: 24),
],
),
),
Padding(
padding: EdgeInsets.all(15),
child: Text(
"Recent Transactions",
style: TextStyle(
fontSize: 14, fontWeight: FontWeight.bold, color: Colors.green),
),
),
ListView() //Display the data here from the REST API
],
)));
}
}
How do I Display it on the Listview? Please I need help with this. Just for the sake of clarification as I am learning here with this.
Try below code:
Your TransactionDetails Class
class TransactionDetails {
String? avatar;
String? name;
String? date;
String? amount;
TransactionDetails({
this.avatar,
this.name,
this.date,
this.amount,
});
TransactionDetails.fromJson(Map<String, dynamic> json) {
avatar = json['avatar'];
name = json['name'];
date = json['date'];
amount = json['amount'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['avatar'] = avatar;
data['name'] = name;
data['date'] = date;
data['amount'] = amount;
return data;
}
}
API Call:
Future<List<TransactionDetails>> fetchAlbum() async {
final response = await http.get(Uri.parse(
'https://brotherlike-navies.000webhostapp.com/people/people.php'));
if (response.statusCode == 200) {
final List result = json.decode(response.body);
return result.map((e) => TransactionDetails.fromJson(e)).toList();
} else {
throw Exception('Failed to load data');
}
}
Your Widget:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: double.infinity,
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
margin: const EdgeInsets.all(15),
width: 319,
height: 100,
color: Colors.green,
alignment: Alignment.center,
child: const Text(
'\$5200.00',
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(15),
width: 319,
height: 100,
color: Colors.green,
alignment: Alignment.center,
child: const Text(
'\$1200.00',
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 24),
],
),
),
const Padding(
padding: EdgeInsets.all(15),
child: Text(
"Recent Transactions",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.green),
),
),
Center(
child: FutureBuilder<List<TransactionDetails>>(
future: fetchAlbum(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
child: Image.network(
snapshot.data![index].avatar.toString()),
),
title: Text(snapshot.data![index].name.toString()),
trailing:
Text(snapshot.data![index].amount.toString()),
subtitle: Text(snapshot.data![index].date.toString()),
);
},
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
),
],
),
Result Screen->
There are multiple ways you can achieve this.
Using FutureBuilder
Using StatefulWidget & setState
Currently, you are using a StatelessWidget (BaseScreen) so let's just go with FutureBuilder.
On hitting the url that you have given:
https://brotherlike-navies.000webhostapp.com/people/people.php
It gives the following response:
[{"avatar":"https:\/\/static.vecteezy.com\/system\/resources\/thumbnails\/002\/002\/403\/small\/man-with-beard-avatar-character-isolated-icon-free-vector.jpg","name":"Kayo Johnson","date":"09\/29\/2022","amount":"5000.00"},{"avatar":"https:\/\/static.vecteezy.com\/system\/resources\/thumbnails\/002\/002\/403\/small\/man-with-beard-avatar-character-isolated-icon-free-vector.jpg","name":"Kuta Joy","date":"09\/29\/2022","amount":"5000.00"},{"avatar":"https:\/\/static.vecteezy.com\/system\/resources\/thumbnails\/001\/993\/889\/small\/beautiful-latin-woman-avatar-character-icon-free-vector.jpg","name":"Timmi Phillips","date":"09\/28\/2022","amount":"3500.00"}]
It returns a list of transaction details objects. Hence, you should add another method in your model TransactionDetail which will return a list of TransactionDetails as follows:
class TransactionDetails {
final String avatar;
final String name;
final String date;
final String amount;
TransactionDetails(
{required this.avatar,
required this.name,
required this.date,
required this.amount});
factory TransactionDetails.fromJson(Map<String, dynamic> json) {
return TransactionDetails(
avatar: json['avatar'],
name: json['name'],
date: json['date'],
amount: json['amount']);
}
static List<TransactionDetails> fromJsonList(dynamic jsonList) {
final transactionDetailsList = <TransactionDetails>[];
if (jsonList == null) return transactionDetailsList;
if (jsonList is List<dynamic>) {
for (final json in jsonList) {
transactionDetailsList.add(
TransactionDetails.fromJson(json),
);
}
}
return transactionDetailsList;
}
}
Update your fetchTransaction method as follows:
Future<List<TransactionDetails>> fetchTransaction() async {
final response = await http
.get('https://brotherlike-navies.000webhostapp.com/people/people.php');
if (response.statusCode == 200) {
return TransactionDetails.fromJsonList(json.decode(response.body));
} else {
throw Exception('Request Failed.');
}
}
Just wrap your ListView widget with a FutureBuilder widget as follows:
FutureBuilder(
future: fetchTransaction(),
builder: (context, AsyncSnapshot<List<TransactionDetails>> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return const Center(child: Text('Something went wrong'));
}
return ListView.builder(
itemCount: snapshot.data?.length ?? 0,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data![index].name),
subtitle: Text(snapshot.data![index].amount),
);
});
}
return const CircularProgressIndicator();
},
),

Flutter: How to print nested map to listView or futurebuilder

I have this response from my server and wants to print the values on screen, values keep returning null.
This is the json response:
{
"responseCode": 99,
"message": "User Found!",
"responseData": {
"id": 10,
"role": {
"id": 1,
"name": "CUSTOMER",
"description": "This is the user of the application"
},
"firstName": "Austin",
"lastName": "Miles",
"createdOn": "2020-05-12T10:25:06.442+00:00",
"dob": null,
"emailAddress": "example#gmail.com",
"phoneNumber": null,
"profilePhotoUrl": null,
"profilePhotoFormat": null,
"isDisabled": false
}
}
This was the class I was using:
import 'dart:convert';
class User {
String firstName;
String lastName;
String password;
String emailAddress;
String phoneNumber;
String profilePhoto;
String role;
String securityKey;
String dob;
String objectId;
User(
{this.firstName,
this.lastName,
this.password,
this.emailAddress,
this.dob,
this.phoneNumber,
this.profilePhoto,
this.role,
this.objectId,
this.securityKey});
factory User.fromJson(Map<String, dynamic> json) => User(
firstName: json['firstName'] as String,
lastName: json['lastName'] as String,
password: json['password']as String,
emailAddress: json['emailAddress']as String,
phoneNumber: json['phoneNumber']as String,
profilePhoto: json['profilePhoto']as String,
role: json['role']as String,
securityKey: json['securityKey']as String,
dob: json['dob']as String,
objectId: json['objectId']as String,
);
Map<String, dynamic> toJson() => {
'firstName': firstName,
'lastName': lastName,
'password': password,
'emailAddress': emailAddress,
'dob': dob,
'phoneNumber': phoneNumber,
'role': role,
'profilePhoto': profilePhoto,
'securityKey': securityKey,
};
#override
String toString() {
return 'User{firstName: $firstName, lastName: $lastName, password: $password,emailAddress: $emailAddress, phoneNumber: $phoneNumber, profilePhoto: $profilePhoto,role: $role, securityKey: $securityKey, objectId: $objectId}';
}
}
// List<User> userFromJson(String jsonData) {
// final data = json.decode(jsonData);
// return List<User>.from(data.map((item) => User.fromJson(item)));
// }
List<User> userFromJson(String str) =>
List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
String userToJson(User data) {
final jsonData = data.toJson();
return json.encode(jsonData);
}
I made this attempt as follows on ProfilePage screen
import 'dart:convert';
import 'package:ars_progress_dialog/ars_progress_dialog.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:project2/toks_model/user.dart';
import 'package:project2/utils/userHandler.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class ProfilePage extends StatefulWidget {
#override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
FlutterSecureStorage storage = FlutterSecureStorage();
UserDialog usd;
User userModel = User();
getUser() async {
String token = await storage.read(key: "token");
progressDialog.show();
http.Response response = await http.get(
Uri.parse("http://BaseUrl/api/user/get-current-user-details"),
headers: {
"Authorization": "Bearer $token",
"Content-type": "application/json",
},
);
var jsonResponse = json.decode(response.body);
setState(() {
userModel = User.fromJson({"responseData": jsonResponse});
print(userModel);
progressDialog.dismiss();
});
}
#override
void initState() {
super.initState();
getUser();
}
ArsProgressDialog progressDialog;
#override
Widget build(BuildContext context) {
progressDialog = ArsProgressDialog(context,
blur: 2,
backgroundColor: Colors.blue[900],
dismissable: false,
loadingWidget: Container(
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
width: 220,
height: 60,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Center(
child: Row(
children: [
CupertinoActivityIndicator(
radius: 20,
),
SizedBox(width: 10),
Text('Please wait...',
style:
TextStyle(fontSize: 13, fontWeight: FontWeight.bold)),
],
)),
),
));
return Scaffold(
body: Stack(
alignment: Alignment.center,
children: <Widget>[
// background image and bottom contents
Column(
children: <Widget>[
Container(
height: 200.0,
decoration: BoxDecoration(
// color: Colors.blue,
image: DecorationImage(
image: AssetImage('asset/pat4.jpg'), fit: BoxFit.cover),
),
child: Center(
child: Text(
'Sample APP' + '\n' + 'Serving your security needs',
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(Icons.person, color: Colors.blueGrey),
SizedBox(width: 10),
Text(
userModel.firstName,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
],
),
Divider(
thickness: 0.8,
),
SizedBox(height: 10),
Row(
children: [
Icon(Icons.mail, color: Colors.blueGrey),
SizedBox(width: 10),
Text(
userModel.emailAddress,
style: TextStyle(fontSize: 14),
),
],
),
SizedBox(height: 10),
Row(
children: [
Icon(Icons.phone, color: Colors.blueGrey),
SizedBox(width: 10),
Text(
userModel.phoneNumber,
style: TextStyle(fontSize: 14),
),
],
),
SizedBox(height: 10),
Text(
"Any thing else...",
style: TextStyle(fontSize: 14),
),
],
),
)
],
),
// Profile image
Positioned(
top: 150.0, // (background container size) - (circle height / 2)
child: Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: userModel.profilePhoto != null
? NetworkImage(userModel.profilePhoto)
: AssetImage("asset/imageicon.png"),
),
),
),
),
],
),
);
}
}
Please any help will be appreciated.
Thanks in anticipation.
As your API result, I think you should modify as below:
var jsonResponse = json.decode(response.body);
setState(() {
userModel = User.fromJson(jsonResponse["responseData"]);
print(userModel);
progressDialog.dismiss();
});
You should use responseData of API result.

only single row comes from the json api

I am beginner in flutter ,I used an API of soccer to get some information of player transferts ,so I have created a model class that contains only the information that I need to ,but when I executed, I had this error:
E/flutter ( 5073): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
E/flutter ( 5073): #0 new Transferts.fromJson (package:tl_fantasy/models/transfert_json.dart:12:26)
E/flutter ( 5073): #1 _PlayerDetailsState.getTeams.<anonymous closure>.<anonymous closure> (package:tl_fantasy/players/player_details.dart:45:45)
So I changed my model class
if i put this in the model class it works when i put it for example json['transfers'][0]['date'], but the problem is it gives me only the first result , what i need is all results, how to replace[0] by a kind of index or something? how to take all elements?
Here the json that i am trying to access:
{
"response": [
{
"player": {
"id": 35845,
"name": "Hernán Darío Burbano"
},
"update": "2020-02-06T00:08:15+00:00",
"transfers": [
{
"date": "2019-07-15",
"type": "Free",
"teams": {
"in": {
"id": 2283,
"name": "Atlas",
"logo": "https://media.api-sports.io/football/teams/2283.png"
}
}
},
{
"date": "2019-01-01",
"type": "N/A",
"teams": {
"in": {
"id": 1937,
"name": "Atletico Atlas",
"logo": "https://media.api-sports.io/football/teams/1937.png"
}
}
}
]
}
]
}
Here my model class tranfert_json:
class Response {
Player player;
String update;
List<Transfers> transfers;
Response({this.player, this.update, this.transfers});
Response.fromJson(Map<String, dynamic> json) {
player = json['player'] != null ? new Player.fromJson(json['player']) : null;
update = json['update'];
if (json['transfers'] != null) {
transfers = new List<Transfers>();
json['transfers'].forEach((v) { transfers.add(new Transfers.fromJson(v)); });
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.player != null) {
data['player'] = this.player.toJson();
}
data['update'] = this.update;
if (this.transfers != null) {
data['transfers'] = this.transfers.map((v) => v.toJson()).toList();
}
return data;
}
}
class Player {
int id;
String name;
Player({this.id, this.name});
Player.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
return data;
}
}
class Transfers {
String date;
String type;
Teams teams;
Transfers({this.date, this.type, this.teams});
Transfers.fromJson(Map<String, dynamic> json) {
date = json['date'];
type = json['type'];
teams = json['teams'] != null ? new Teams.fromJson(json['teams']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['date'] = this.date;
data['type'] = this.type;
if (this.teams != null) {
data['teams'] = this.teams.toJson();
}
return data;
}
}
class Teams {
In teamIn;
Teams({this.teamIn});
Teams.fromJson(Map<String, dynamic> json) {
teamIn = json['in'] != null ? new In.fromJson(json['in']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.teamIn != null) {
data['in'] = this.teamIn.toJson();
}
return data;
}
}
class In {
int id;
String name;
String logo;
In({this.id, this.name, this.logo});
In.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
logo = json['logo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['logo'] = this.logo;
return data;
}
}
Here my player_details class:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:tl_fantasy/models/transfert_json.dart';
class PlayerDetails extends StatefulWidget {
int id;
String name;
String lastname;
String image;
String club;
String position;
String nationality;
String age;
int matches;
String goals;
String assists;
String saves;
PlayerDetails({this.id,this.name, this.lastname,this.image, this.club, this.position,
this.nationality, this.age, this.matches, this.goals, this.assists, this.saves});
#override
_PlayerDetailsState createState() => _PlayerDetailsState();
}
class _PlayerDetailsState extends State<PlayerDetails> {
List<Response> teams = [];
Future<void> getTeams(int id) async {
http.Response response = await http.get(
'https://v3.football.api-sports.io/transfers?player=$id',
headers: {'x-rapidapi-key': 'c52370f8295e1525b7f7ba38655e243f',
'x-rapidapi-host':'v3.football.api-sports.io'});
String body = response.body;
var data = jsonDecode(body);
List<dynamic> clubList = data['response'];
setState(() {
teams = clubList
.map((dynamic item) => Response.fromJson(item))
.toList();
});
}
#override
void initState() {
super.initState();
getTeams(widget.id);
}
#override
Widget build(BuildContext context) {
if(widget.matches == null ){
widget.matches == 0;
}
if(widget.goals == null ){
widget.goals == "0";
}
if(widget.assists == null ){
widget.assists == "0";
}
if(widget.saves == null ){
widget.saves == "0";
}
List<Stats> stats = [
Stats("Matches", widget.matches.toString() ),
Stats("Goals", widget.goals ),
Stats("Assists", widget.assists ),
Stats("Saves", widget.saves ),
];
return Scaffold(
appBar: AppBar(
title: Text("Player Details"),
backgroundColor: Colors.blue[300],
elevation: 0.0,
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Colors.purple, Colors.blue])
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.purple, Colors.black38])),
child: ListView(
children: [
SizedBox(
height: 20,
),
Container(
margin: EdgeInsets.fromLTRB(8.0,0,8.0,0),
width: double.infinity,
child: Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child:
Row(
children: <Widget>[
Container(
height: 60,
width: 60,
child:
Image.network(this.widget.image,
),
),
const SizedBox(width:10.0),
Spacer(),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget> [
Text(widget.name, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0,
)),
Text(widget.lastname, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0,
)),
const SizedBox(height: 5.0, ),
Text(widget.club, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0,
)),
const SizedBox(height: 5.0, ),
Text("Role : "+widget.position, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0, color: Colors.grey[600],
)),
const SizedBox(height: 5.0, ),
Text("Age : "+widget.age, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0, color: Colors.grey[600],
)),
const SizedBox(height: 5.0, ),
Text("Nationality : "+widget.nationality, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0, color: Colors.grey[600],
)),
],
),
],
),
),
),
),
Container(
margin: EdgeInsets.fromLTRB(10, 15, 0, 0),
child: Text(
"Season Stats",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w900, color: Colors.white),
),
),
SizedBox(
height: 10,
),
Container(
padding: EdgeInsets.all(12.0),
child: GridView.builder(
shrinkWrap: true,
itemCount: stats.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0
),
itemBuilder: (BuildContext context, int index){
return Card(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.fromLTRB(0, 5, 0, 0),
child: Text(stats[index].result,style: TextStyle(fontSize: 20.0)),
),
Container(
alignment: Alignment.bottomCenter,
child: Text(stats[index].title,style: TextStyle(fontSize: 25.0)),),
]
),
),
);
},
)
),
SizedBox(
height: 10,
),
Container(
margin: EdgeInsets.fromLTRB(10, 0, 0, 10),
child: Text(
"Teams",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w900, color: Colors.white),
),
),
SizedBox(
height: 10,
),
Container(
margin: EdgeInsets.fromLTRB(5, 0, 5, 0),
child: ListView.builder(
shrinkWrap: true,
physics : NeverScrollableScrollPhysics(),
itemBuilder: (context, index){
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child:
Row(
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(teams[index].transfers[index].teams.teamIn.logo),
),
const SizedBox(width:10.0),
Spacer(),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget> [
Text(teams[index].transfers[index].teams.teamIn.name, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0,
)),
const SizedBox(height: 5.0, ),
Text("joined : "+teams[index].transfers[index].date, style: TextStyle( fontWeight:FontWeight.bold,
fontSize: 18.0, color: Colors.grey[600],
)),
],
),
],
),
),
);
},
itemCount: teams.length,
),
),
SizedBox(
height: 70,
),
],
),
)
),
);
}
}
class Stats{
String title;
String result;
Stats(this.title,this.result);
}
class Team {
String name;
String image;
String date;
Team(this.name,this.image,this.date);
}
i am trying to find a way to get all results , not just the first index of my api json
Example of nested ListviewBuilder , don't forget to add shrinkWrap inside the listview
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: teams.length,
itemBuilder: (BuildContext context, int index) {
List<Transfers> transfers = teams[index].transfers;
return ListView.builder(
shrinkWrap: true,
itemCount: transfers.length,
itemBuilder: (BuildContext context, int index) {
return Text(transfers[index].teams.teamIn.name);
},
) ;
},
),
);
}

How to populating 2nd DropdownMenu based on first item selected flutter

I'm populating states name from JSON and display as a dropdown list after that I show 2nd dropdown list based on first value selected. But I don't now how to populate 2nd dropdown when 1st dropdown value changed. I also want to get location id, name and city when select 2nd dropdown value.
My Json
{
"data": [
{
"state": "TEXAS",
"locations": [
{
"id": 1,
"name": "FITT Sugarland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "HOUSTON SUGARLAND",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:17:55.000Z",
"modifiedAt": "2020-08-18T10:17:55.000Z"
},
{
"id": 2,
"name": "FITT Pearland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "second location",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:18:38.000Z",
"modifiedAt": "2020-08-18T10:18:38.000Z"
}
]
}
]
}
Model Class
class LocationModel {
List<LocationList> data;
LocationModel({this.data});
LocationModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = new List<LocationList>();
json['data'].forEach((v) {
data.add(new LocationList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class LocationList {
String state;
List<Locations> locations;
LocationList({this.state, this.locations});
LocationList.fromJson(Map<String, dynamic> json) {
state = json['state'];
if (json['locations'] != null) {
locations = new List<Locations>();
json['locations'].forEach((v) {
locations.add(new Locations.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['state'] = this.state;
if (this.locations != null) {
data['locations'] = this.locations.map((v) => v.toJson()).toList();
}
return data;
}
}
class Locations {
int id;
String name;
String city;
String state;
String timezone;
String ownerName;
String ownerPhoneNumber;
String ownerEmail;
String ownerWebsite;
int capacity;
String description;
String createdBy;
String modifiedBy;
String createdAt;
String modifiedAt;
Locations(
{this.id,
this.name,
this.city,
this.state,
this.timezone,
this.ownerName,
this.ownerPhoneNumber,
this.ownerEmail,
this.ownerWebsite,
this.capacity,
this.description,
this.createdBy,
this.modifiedBy,
this.createdAt,
this.modifiedAt});
Locations.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
city = json['city'];
state = json['state'];
timezone = json['timezone'];
ownerName = json['ownerName'];
ownerPhoneNumber = json['ownerPhoneNumber'];
ownerEmail = json['ownerEmail'];
ownerWebsite = json['ownerWebsite'];
capacity = json['capacity'];
description = json['description'];
createdBy = json['createdBy'];
modifiedBy = json['modifiedBy'];
createdAt = json['createdAt'];
modifiedAt = json['modifiedAt'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['city'] = this.city;
data['state'] = this.state;
data['timezone'] = this.timezone;
data['ownerName'] = this.ownerName;
data['ownerPhoneNumber'] = this.ownerPhoneNumber;
data['ownerEmail'] = this.ownerEmail;
data['ownerWebsite'] = this.ownerWebsite;
data['capacity'] = this.capacity;
data['description'] = this.description;
data['createdBy'] = this.createdBy;
data['modifiedBy'] = this.modifiedBy;
data['createdAt'] = this.createdAt;
data['modifiedAt'] = this.modifiedAt;
return data;
}
}
My Code
import 'dart:io';
import 'package:fittheorem/models/location_list.dart';
import 'package:fittheorem/providers/auth_session.dart';
import 'package:fittheorem/providers/user_details.dart';
import 'package:fittheorem/ui/widgets/error_snakbar.dart';
import 'package:fittheorem/utils/app_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class LocationUpdate extends StatefulWidget {
#override
_LocationUpdateState createState() => _LocationUpdateState();
}
class _LocationUpdateState extends State<LocationUpdate> {
LocationModel _locationModel;
bool isLoading = true;
String _selectedState = "TEXAS";
List<String> _statesList = [];
String _selectedLocation = "FITT Sugarland";
List<Locations> _locationsList = List();
#override
void initState() {
// TODO: implement initState
super.initState();
getList();
}
Future<void> getList() async {
try {
_locationModel = await Provider.of<UserDetails>(context, listen: false)
.getLocationList("token");
for (int i = 0; i < _locationModel.data.length; i++) {
_statesList.add(_locationModel.data[i].state);
}
_locationsList = _locationModel.data[0].locations;
_selectedState = _statesList[0];
_selectedLocation = _locationsList[0].name;
if (mounted) {
setState(() {
isLoading = false;
});
}
} on HttpException catch (error) {
CustomWidgets.buildErrorSnackbar(context);
} catch (error) {
CustomWidgets.buildErrorSnackbar(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: AppConfig.bgColor,
child: SafeArea(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
height: 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context, true);
},
child: Container(
height: 25.0,
width: 25.0,
child: SvgPicture.asset(AppConfig.backImage,
color: Colors.white, semanticsLabel: 'back')),
),
Text('LOCATION',
style: GoogleFonts.roboto(
textStyle: TextStyle(
fontSize: 18.0, color: Color(0xffFFFFFF)),
)),
SizedBox(
width: 25.0,
),
],
),
),
Expanded(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(30.0),
child: isLoading
? Center(
child: AppConfig().myLoader(),
)
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 20.0,
),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text('UPDATE YOUR LOCATION',
style: GoogleFonts.roboto(
textStyle: TextStyle(
fontSize: 16.0,
color: Color(0xff000000)),
)),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.black54, width: 0.0),
borderRadius: new BorderRadius.circular(10.0),
),
child: new DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: new DropdownButton(
value: _selectedState,
hint: Text("State"),
isExpanded: true,
items: _statesList
.map((String item) =>
DropdownMenuItem<String>(
child: Text(item),
value: item))
.toList(),
onChanged: (String newValue) {
if (mounted)
setState(() {
_selectedState = newValue;
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.black54, width: 0.0),
borderRadius: new BorderRadius.circular(10.0),
),
child: new DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: new DropdownButton(
value: _selectedLocation,
hint: Text("Location"),
isExpanded: true,
items: _locationsList.map((item) {
return new DropdownMenuItem(
child: new Text(item.name),
value: item.name,
);
}).toList(),
onChanged: (newValue) {
if (mounted) print(newValue);
setState(() {
_selectedLocation = newValue;
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
)
],
),
),
)
],
),
),
),
);
}
}
You can copy paste run full code below
Step 1: Change data type of _selectedLocation
Locations _selectedLocation;
Step 2: _selectedState's onChanged
onChanged: (String Value) {
if (mounted)
setState(() {
_selectedState = Value;
int index = _locationModel.data
.indexWhere((element) =>
element.state ==
_selectedState);
_locationsList = _locationModel
.data[index].locations;
_selectedLocation =
_locationsList[0];
});
},
Step 3: _selectedLocation's onChanged
onChanged: (Value) {
if (mounted) print(Value);
setState(() {
_selectedLocation = Value;
print(
"${_selectedLocation.name} ${_selectedLocation.id} ${_selectedLocation.city}");
});
},
working demo
full code
import 'dart:convert';
import 'package:flutter/material.dart';
LocationModel locationModelFromJson(String str) =>
LocationModel.fromJson(json.decode(str));
class LocationModel {
List<LocationList> data;
LocationModel({this.data});
LocationModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = List<LocationList>();
json['data'].forEach((v) {
data.add(LocationList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class LocationList {
String state;
List<Locations> locations;
LocationList({this.state, this.locations});
LocationList.fromJson(Map<String, dynamic> json) {
state = json['state'];
if (json['locations'] != null) {
locations = List<Locations>();
json['locations'].forEach((v) {
locations.add(Locations.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['state'] = this.state;
if (this.locations != null) {
data['locations'] = this.locations.map((v) => v.toJson()).toList();
}
return data;
}
}
class Locations {
int id;
String name;
String city;
String state;
String timezone;
String ownerName;
String ownerPhoneNumber;
String ownerEmail;
String ownerWebsite;
int capacity;
String description;
String createdBy;
String modifiedBy;
String createdAt;
String modifiedAt;
Locations(
{this.id,
this.name,
this.city,
this.state,
this.timezone,
this.ownerName,
this.ownerPhoneNumber,
this.ownerEmail,
this.ownerWebsite,
this.capacity,
this.description,
this.createdBy,
this.modifiedBy,
this.createdAt,
this.modifiedAt});
Locations.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
city = json['city'];
state = json['state'];
timezone = json['timezone'];
ownerName = json['ownerName'];
ownerPhoneNumber = json['ownerPhoneNumber'];
ownerEmail = json['ownerEmail'];
ownerWebsite = json['ownerWebsite'];
capacity = json['capacity'];
description = json['description'];
createdBy = json['createdBy'];
modifiedBy = json['modifiedBy'];
createdAt = json['createdAt'];
modifiedAt = json['modifiedAt'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['city'] = this.city;
data['state'] = this.state;
data['timezone'] = this.timezone;
data['ownerName'] = this.ownerName;
data['ownerPhoneNumber'] = this.ownerPhoneNumber;
data['ownerEmail'] = this.ownerEmail;
data['ownerWebsite'] = this.ownerWebsite;
data['capacity'] = this.capacity;
data['description'] = this.description;
data['createdBy'] = this.createdBy;
data['modifiedBy'] = this.modifiedBy;
data['createdAt'] = this.createdAt;
data['modifiedAt'] = this.modifiedAt;
return data;
}
}
class LocationUpdate extends StatefulWidget {
#override
_LocationUpdateState createState() => _LocationUpdateState();
}
class _LocationUpdateState extends State<LocationUpdate> {
LocationModel _locationModel;
bool isLoading = true;
String _selectedState = "TEXAS";
List<String> _statesList = [];
Locations _selectedLocation;
List<Locations> _locationsList = List();
#override
void initState() {
// TODO: implement initState
super.initState();
getList();
}
Future<void> getList() async {
try {
/*_locationModel = await Provider.of<UserDetails>(context, listen: false)
.getLocationList("token");*/
String jsonString = '''
{
"data": [
{
"state": "TEXAS",
"locations": [
{
"id": 1,
"name": "FITT Sugarland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "HOUSTON SUGARLAND",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:17:55.000Z",
"modifiedAt": "2020-08-18T10:17:55.000Z"
},
{
"id": 2,
"name": "FITT Pearland",
"city": "HOUSTON",
"state": "TEXAS",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "second location",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:18:38.000Z",
"modifiedAt": "2020-08-18T10:18:38.000Z"
}
]
},
{
"state": "A",
"locations": [
{
"id": 1,
"name": "A1",
"city": "A City 1",
"state": "A",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "HOUSTON SUGARLAND",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:17:55.000Z",
"modifiedAt": "2020-08-18T10:17:55.000Z"
},
{
"id": 2,
"name": "A2",
"city": "A city 2",
"state": "A",
"timezone": "",
"ownerName": "",
"ownerPhoneNumber": "",
"ownerEmail": "",
"ownerWebsite": "",
"capacity": 0,
"description": "second location",
"createdBy": "",
"modifiedBy": "",
"createdAt": "2020-08-18T10:18:38.000Z",
"modifiedAt": "2020-08-18T10:18:38.000Z"
}
]
}
]
}
''';
_locationModel = locationModelFromJson(jsonString);
for (int i = 0; i < _locationModel.data.length; i++) {
_statesList.add(_locationModel.data[i].state);
}
_locationsList = _locationModel.data[0].locations;
_selectedState = _statesList[0];
_selectedLocation = _locationsList[0];
if (mounted) {
setState(() {
isLoading = false;
});
}
//} on HttpException catch (error) {
// CustomWidgets.buildErrorSnackbar(context);
} catch (error) {
//CustomWidgets.buildErrorSnackbar(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
//color: AppConfig.bgColor,
child: SafeArea(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
height: 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context, true);
},
child: Container(
height: 25.0,
width: 25.0,
child: Image.network(
'https://picsum.photos/250?image=9',
color: Colors.white)),
),
Text('LOCATION',
style: TextStyle(
fontSize: 18.0,
color: Color(0xffFFFFFF),
)),
SizedBox(
width: 25.0,
),
],
),
),
Expanded(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(30.0),
child: isLoading
? Center(
child: CircularProgressIndicator(),
)
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 20.0,
),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text('UPDATE YOUR LOCATION',
style: TextStyle(
fontSize: 16.0,
color: Color(0xff000000),
)),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black54, width: 0.0),
borderRadius: BorderRadius.circular(10.0),
),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: _selectedState,
hint: Text("State"),
isExpanded: true,
items: _statesList
.map((String item) =>
DropdownMenuItem<String>(
child: Text(item),
value: item))
.toList(),
onChanged: (String Value) {
if (mounted)
setState(() {
_selectedState = Value;
int index = _locationModel.data
.indexWhere((element) =>
element.state ==
_selectedState);
_locationsList = _locationModel
.data[index].locations;
_selectedLocation =
_locationsList[0];
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
),
SizedBox(
height: 20.0,
),
Container(
height: 40.0,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black54, width: 0.0),
borderRadius: BorderRadius.circular(10.0),
),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: _selectedLocation,
hint: Text("Location"),
isExpanded: true,
items: _locationsList.map((item) {
return DropdownMenuItem(
child: Text(item.name),
value: item,
);
}).toList(),
onChanged: (Value) {
if (mounted) print(Value);
setState(() {
_selectedLocation = Value;
print(
"${_selectedLocation.name} ${_selectedLocation.id} ${_selectedLocation.city}");
});
},
style: Theme.of(context)
.textTheme
.bodyText2,
))),
)
],
),
),
)
],
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: LocationUpdate(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}