Home > Enterprise >  Flutter/dart: how to render LinkedMap<dynamic, dynamic> to listview.builder
Flutter/dart: how to render LinkedMap<dynamic, dynamic> to listview.builder

Time:11-18

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

  • Related