So I have this data from api that then gives me a _JsonMap response which I then convert to LinkedMap<dyanmic, dynamic> by doing:
final data = Map.from(response.data);
Now I have this LinkedMap<dyanmic, dynamic> data which looks like this.
{
Product1: {
name: 'name',
description: 'description',
Promos: {
Price1: {
amount: 999,
metadata: {
dateStart: 2022-11-23
dateEnd: 2022-11-25
promoName: test,
}
}
Price2: {
amount: 999,
metadata: {
dateStart: 2022-11-23
dateEnd: 2022-11-25
promoName: test,
}
}
Price3: {
amount: 999,
metadata: {
dateStart: 2022-11-23
dateEnd: 2022-11-25
promoName: test,
}
}
}
}
Product2: {
name: 'name',
description: 'description',
Promos: {
Price1: {
amount: 999,
metadata: {
dateStart: 2022-11-23
dateEnd: 2022-11-25
promoName: test,
}
}
Price2: {
amount: 999,
metadata: {
dateStart: 2022-11-23
dateEnd: 2022-11-25
promoName: test,
}
}
Price3: {
amount: 999,
metadata: {
dateStart: 2022-11-23
dateEnd: 2022-11-25
promoName: test,
}
}
}
}
}
Now what i'm trying to do is Map the Producst - get to their Promos - get the all Prices - then get to their metadata and display dateStart, dateEnd, promoName to my listview.builder. any ideas?
response.data
{
"Product1":{
"name":"name",
"description":"test",
"Promos":{
"Price1":{
"amount":"999",
"metadata":{
"dateStart":"2022-11-23",
"dateEnd":"2022-11-25",
"promoName":"test"
}
},
"Price2":{
"amount":"999",
"metadata":{
"dateStart":"2022-11-23",
"dateEnd":"2022-11-25",
"promoName":"test"
}
},
"Price3":{
"amount":"999",
"metadata":{
"dateStart":"2022-11-23",
"dateEnd":"2022-11-25",
"promoName":"test"
}
}
}
},
"Product2":{
"name":"name",
"description":"test",
"Promos":{
"Price1":{
"amount":"999",
"metadata":{
"dateStart":"2022-11-23",
"dateEnd":"2022-11-25",
"promoName":"test"
}
},
"Price2":{
"amount":"999",
"metadata":{
"dateStart":"2022-11-23",
"dateEnd":"2022-11-25",
"promoName":"test"
}
},
"Price3":{
"amount":"999",
"metadata":{
"dateStart":"2022-11-23",
"dateEnd":"2022-11-25",
"promoName":"test"
}
}
}
}
}
CodePudding user response:
Just Copy and Paste; Then carefully Study it; The Trick is to use MapEntry i.e Convert your data to a List by doing data.entries.toList();
import 'package:flutter/material.dart';
import 'package:grouped_list/grouped_list.dart';
final data = {
"Product1": {
"name": "theodore",
"description": "test",
"Promos": {
"Price1": {
"amount": "999",
"metadata": {
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
},
"Price2": {
"amount": "999",
"metadata": {
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
},
"Price3": {
"amount": "999",
"metadata": {
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
}
}
},
"Product2": {
"name": "cynthia",
"description": "test",
"Promos": {
"Price1": {
"amount": "999",
"metadata": {
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
},
"Price2": {
"amount": "999",
"metadata": {
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
},
"Price3": {
"amount": "999",
"metadata": {
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
}
}
}
};
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Grouped List View Example'),
),
body: GroupedListView<dynamic, String>(
elements: data.entries.toList(),
groupBy: (element) => element.value["name"],
groupComparator: (value1, value2) => value2.compareTo(value1),
itemComparator: (item1, item2) =>
item1['name'].compareTo(item2['name']),
order: GroupedListOrder.DESC,
useStickyGroupSeparators: true,
groupSeparatorBuilder: (String value) => Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
value,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
itemBuilder: (c, element) {
return Column(
children: (element.value["Promos"].entries.toList()
as List<MapEntry>)
.map((promo) => Card(
elevation: 8.0,
margin: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 6.0),
child: SizedBox(
child: ListTile(
contentPadding: const EdgeInsets.symmetric(
horizontal: 20.0, vertical: 10.0),
leading: const Icon(Icons.card_giftcard),
title: Text(promo.key
"-"
" "
promo.value["metadata"]["promoName"]),
subtitle: Text(promo.value["metadata"]["dateEnd"]),
trailing: Text(promo.value["amount"]),
),
),
))
.toList(),
);
},
),
),
);
}
}
CodePudding user response:
First your response data should look like this
[
{
"name": "Product 1",
"description": "test",
"promos": [
{
"name": "Price 1",
"amount": "999",
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
},
{
"name": "Price 2",
"amount": "999",
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
},
{
"name": "Price 3",
"amount": "999",
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
]
},
{
"name": "Product 2",
"description": "test",
"promos": [
{
"name": "Price 1",
"amount": "999",
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
},
{
"name": "Price 2",
"amount": "999",
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
},
{
"name": "Price 3",
"amount": "999",
"dateStart": "2022-11-23",
"dateEnd": "2022-11-25",
"promoName": "test"
}
]
}
]
then you need to serialize the reponse data
sample_model.dart
import 'dart:convert';
class Products {
Products({
required this.name,
required this.description,
required this.promos,
});
String name;
String description;
List<Promo> promos;
factory Products.fromJson(Map<String, dynamic> json) => Products(
name: json["name"],
description: json["description"],
promos: List<Promo>.from(json["promos"].map((x) => Promo.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"name": name,
"description": description,
"promos": List<dynamic>.from(promos.map((x) => x.toJson())),
};
}
class Promo {
Promo({
required this.name,
required this.amount,
required this.dateStart,
required this.dateEnd,
required this.promoName,
});
String name;
String amount;
DateTime dateStart;
DateTime dateEnd;
String promoName;
factory Promo.fromJson(Map<String, dynamic> json) => Promo(
name: json["name"],
amount: json["amount"],
dateStart: DateTime.parse(json["dateStart"]),
dateEnd: DateTime.parse(json["dateEnd"]),
promoName: json["promoName"],
);
Map<String, dynamic> toJson() => {
"name": name,
"amount": amount,
"dateStart":
"${dateStart.year.toString().padLeft(4, '0')}-${dateStart.month.toString().padLeft(2, '0')}-${dateStart.day.toString().padLeft(2, '0')}",
"dateEnd":
"${dateEnd.year.toString().padLeft(4, '0')}-${dateEnd.month.toString().padLeft(2, '0')}-${dateEnd.day.toString().padLeft(2, '0')}",
"promoName": promoName,
};
}
then use the sample_model.dart
method on your controller or view
final data = List<Products>.from(response.data.map((x) => Products.fromJson(x)));
finally, on ListView.builder
ListView.builder(
itemCount: controller.data.length,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(controller.data[index].name),
Text(controller.data[index].promos[0].name),
Text(controller.data[index].promos[0].amount),
Text(controller.data[index].promos[1].name),
Text(controller.data[index].promos[1].amount),
Text(controller.data[index].promos[2].name),
Text(controller.data[index].promos[2].amount),
],
),
),
);
},
),
Gists: Complete code here. Copy & paste it on dartpad.dev to see the result