I have the below list of objects that am trying to make into an expandable list grouped by month. Which is a value in the list.
{
"status":"Success",
"payments":[
{
"id":291,
"user":{
"id":12,
"userID":"cvWLyHRla",
"name":"Bill Obama",
"email":"email@user1",
"username":"username1",
"profilePic":null,
"created_at":"2023-05-08T00:52:11.000000Z"
},
"userID":12,
"groupID":28,
"paymentDueDate":"2023-11-01",
"paymentDate":null,
"amount":1000,
"forDuration":"November",
"proofOfPayment":null,
"paymentMode":null,
"paymentID":null,
"paymentToken":null,
"approvedBy":null,
"approvedByUser":null,
"approvedAt":null,
"created_at":"2023-10-30T07:52:30.000000Z",
"status":"pending",
},
{
"id":290,
"user":{
"id":8,
"userID":"yuwrgojsvIXqGeAzT18bTxbObEG3",
"name":"Obama Clinton",
"email":"email@user2",
"username":"username2",
"profilePic":"645866b914fu.jpg",
"created_at":"2023-05-07T23:01:24.000000Z"
},
"userID":8,
"groupID":28,
"paymentDueDate":"2023-11-01",
"paymentDate":"2023-10-30",
"amount":1000,
"forDuration":"November",
"proofOfPayment":null,
"paymentMode":"MobileMoney",
"paymentID":"5888699-999",
"paymentToken":null,
"approvedBy":null,
"approvedByUser":null,
"approvedAt":"2023-10-30 07:53:15",
"created_at":"2023-10-30T07:52:30.000000Z",
"status":"paid",
}
]
}
Am trying to create a flutter expandable list based on the "forDuration". So for each "forDuration" i should have children of the name, email, amount for all Users for that period. I have the below Listview.builder code but it is not showing the expansion tiles. Please kindly help. Below is what i have tried but the outcome is not as desired.
ListView.builder(
itemCount: controller.groupPaymentResponse.value?.payments?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
var e = controller.groupPaymentResponse.value!.payments![index];
bool sameforDuration = false;
if (controller.groupPaymentResponse.value!.payments![index + 1].forDuration ==
controller.groupPaymentResponse.value!.payments![index]) {
bool sameforDuration = true;
}
var image = e.user!.profilePic == null ? userPlaceHolder : "${e.user!.imagePath}/${e.user!.profilePic}";
return ExpansionTile(
title: Text(
e.forDuration.toString(),
),
children: [Text(e.user!.name!), Text(e.user!.email!), Text(e.amount.toString())],
);
}),
You need to modify(group
) your list to get this result
You can run it in dartpad I already coded it and need just a click on that link. Output is following screenshot
import 'package:flutter/material.dart';
import "package:collection/collection.dart";
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late Map<String, List<TestingObj>> groupedItemMap;
List<TestingObj> testingItems = [
TestingObj(
"Book",
"100000",
"November",
),
TestingObj(
"Pencil",
"100",
"November",
),
TestingObj(
"Eraser",
"1000",
"December",
),
TestingObj(
"Ruler",
"100000",
"September",
),
TestingObj(
"Bag",
"100000",
"September",
),
TestingObj(
"Paper",
"100000",
"September",
),
];
@override
void initState() {
groupedItemMap = groupBy(testingItems, (entry) => entry.month);
print(groupedItemMap.toString());
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemBuilder: (context, index) => ExpansionTile(
title: Text(
groupedItemMap.entries.elementAt(index).key,
),
children: groupedItemMap.entries
.elementAt(index)
.value
.map((item) => Text(item.itemName))
.toList(),
),
itemCount: groupedItemMap.length),
);
}
}
class TestingObj {
final String itemName;
final String profit;
final String month;
TestingObj(this.itemName, this.profit, this.month);
}