简体   繁体   中英

Issue Rendering Data using ListView.builder

The idea is to render data from the below JSON in the two following ways:

The expected outputs are

  1. Display all ie all the serial_number and name properties like

    0001 Mr.A 0002 Mr.B 0003 Mr.C 0004 Mr.D and so on

  2. Display only the grievance properties

    0001 Mr.A 0002 Mr.B 0005 Mr.E 0006 Mr.F 0009 Mr.I 0010 Mr.J 0013 Mr.M 0014 Mr.N

This is the JSON(response) data:

[
    {
        "district": "Kolkata",
        "ward_no": [
            {
                "ward": "6",
                "grievance": [
                    {
                        "serial_number": "0001",
                        "name" : "Mr.A"
                    },
                    {
                        "serial_number": "0002",
                        "name" : "Mr.B"
                    }
                ],
                "general": [
                    {
                        "serial_number": "0003",
                        "name" : "Mr.C"
                    },
                    {
                        "serial_number": "0004",
                        "name" : "Mr.D"
                    }
                ]
            },
            {
                "ward": "7",
                "grievance": [
                    {
                        "serial_number": "0005",
                        "name" : "Mr.E"
                    },
                    {
                        "serial_number": "0006",
                        "name" : "Mr.F"
                    }
                ],
                "general": [
                    {
                        "serial_number": "0007",
                        "name" : "Mr.G"
                    },
                    {
                        "serial_number": "0008",
                        "name" : "Mr.H"
                    }
                ]
            }
        ]
    },
    {
        "district": "Hooghly",
        "ward_no": [
            {
                "ward": "8",
                "grievance": [
                    {
                        "serial_number": "0009",
                        "name" : "Mr.I"
                    },
                    {
                        "serial_number": "0010",
                        "name" : "Mr.J"
                    }
                ],
                "general": [
                    {
                        "serial_number": "0011",
                        "name" : "Mr.K"
                    },
                    {
                        "serial_number": "0012",
                        "name" : "Mr.L"
                    }
                ]
            },
            {
                "ward": "9",
                "grievance": [
                    {
                        "serial_number": "0013",
                        "name" : "Mr.M"
                    },
                    {
                        "serial_number": "0014",
                        "name" : "Mr.N"
                    }
                ],
                "general": [
                    {
                        "serial_number": "0015",
                        "name" : "Mr.O"
                    },
                    {
                        "serial_number": "0018",
                        "name" : "Bruno Fernandes"
                    }
                ]
            }
        ]
    }
]

This is the model class of the response received from making a GET API Call:

import 'dart:convert';

List<User> userFromJson(String str) => List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
String userToJson(List<User> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class User {
  String? id;
  String? district;
  List<WardNo>? wardNo;

  User({this.id, this.district, this.wardNo});

  User.fromJson(Map<String, dynamic> json) {
    this.id = json["_id"];
    this.district = json["district"];
    this.wardNo = json["ward_no"]==null ? null : (json["ward_no"] as List).map((e)=>WardNo.fromJson(e)).toList();
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["_id"] = this.id;
    data["district"] = this.district;
    if(this.wardNo != null)
      data["ward_no"] = this.wardNo?.map((e)=>e.toJson()).toList();
    return data;
  }
}


class WardNo {
  String? ward;
  List<Grievance>? grievance;
  List<General>? general;

  WardNo({this.ward, this.grievance, this.general, this.urgent, this.services});

  WardNo.fromJson(Map<String, dynamic> json) {
    this.ward = json["ward"];
    this.grievance = json["grievance"]==null ? null : (json["grievance"] as List).map((e)=>Grievance.fromJson(e)).toList();
    this.general = json["general"]==null ? null : (json["general"] as List).map((e)=>General.fromJson(e)).toList();
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["ward"] = this.ward;
    if(this.grievance != null)
      data["grievance"] = this.grievance?.map((e)=>e.toJson()).toList();
    if(this.general != null)
      data["general"] = this.general?.map((e)=>e.toJson()).toList();
    return data;
  }
}


class General {
  String? serialNumber;
  String? name;

  General({this.serialNumber, this.name});

  General.fromJson(Map<String, dynamic> json) {
    this.serialNumber = json["serial_number"];
    this.name = json["name"];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["serial_number"] = this.serialNumber;
    data["name"] = this.name;
    return data;
  }
}

class Grievance {
  String? serialNumber;
  String? name;

  Grievance({this.serialNumber, this.name});

  Grievance.fromJson(Map<String, dynamic> json) {
    this.serialNumber = json["serial_number"];
    this.name = json["name"];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["serial_number"] = this.serialNumber;
    data["name"] = this.name;
    return data;
  }
}

The class that calls the API:

class ModelClass with ChangeNotifier {
  List<dynamic> _data = [];

  List<dynamic> get data {
    return [..._data];
  }

  Future<void> getData() async {
    final url = Uri.http('192.168.0.6:3007', '/fetchData');
    final response = await http.get(url);
    print(response);
    final List<User> users = userFromJson(response.body);
    print(users);
    _data = users;
    print(_data);
  }
}

The widget class where I want the data to be displayed:

class MainScreen extends StatefulWidget {
  MainScreenState createState() => MainScreenState();
}

class MainScreenState extends State<MainScreen> {
  var clicked = false;

  @override
  void initState() {
    Provider.of<ModelClass>(context, listen: false).getData();
    super.initState();
  }

  void clickedButton() async {
    await Provider.of<ModelClass>(context, listen: false).getData();
    print('clicked');
    setState(() {
      clicked = !clicked;
    });
  }

  @override
  Widget build(BuildContext context) {
    final provider = Provider.of<ModelClass>(context).data;

    // TODO: implement build
    return Scaffold(
        appBar: AppBar(
          title: Text("Demo App"),
        ),
        body: !clicked
            ? Center(
                child: ElevatedButton(
                    child: Text('Click Me'), onPressed: clickedButton))
            : ListView.builder(
                itemBuilder: (context, index) =>
                  Row(
                    children: [
                      Text(provider[0].wardNo[0].grievance[index].serialNumber), //*
                      SizedBox(width: 10),
                      Text(provider[0].wardNo[0].grievance[index].name)  //*
                    ],
                  ),
                  itemCount: provider[0].wardNo[0].grievance.length,

              ));
  }
}

Right now, the lines marked in the above widget renders the following output: 0001 Mr.A 0002 Mr.BI would like to know what I need to do to render through the JSON in a way that would render the data exactly the way I stated above.

I have modified the code as you stated: the boolean field showGrievanceOnly in MainScreen is used to denote if we want to show grievance data only or not. This is User class:

import 'dart:convert';

List<User> userFromJson(String str) => List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
String userToJson(List<User> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class User {
  String? id;
  String? district;
  List<WardNo>? wardNo;

  User({this.id, this.district, this.wardNo});

  User.fromJson(Map<String, dynamic> json) {
    this.id = json["_id"];
    this.district = json["district"];
    this.wardNo = json["ward_no"]==null ? null : (json["ward_no"] as List).map((e)=>WardNo.fromJson(e)).toList();
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["_id"] = this.id;
    data["district"] = this.district;
    if(this.wardNo != null)
      data["ward_no"] = this.wardNo?.map((e)=>e.toJson()).toList();
    return data;
  }
}


class WardNo {
  String? ward;
  List<Grievance>? grievance;
  List<General>? general;

  WardNo({this.ward, this.grievance, this.general});

  WardNo.fromJson(Map<String, dynamic> json) {
    this.ward = json["ward"];
    this.grievance = json["grievance"]==null ? null : (json["grievance"] as List).map((e)=>Grievance.fromJson(e)).toList();
    this.general = json["general"]==null ? null : (json["general"] as List).map((e)=>General.fromJson(e)).toList();
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["ward"] = this.ward;
    if(this.grievance != null)
      data["grievance"] = this.grievance?.map((e)=>e.toJson()).toList();
    if(this.general != null)
      data["general"] = this.general?.map((e)=>e.toJson()).toList();
    return data;
  }
}


class General {
  String? serialNumber;
  String? name;

  General({this.serialNumber, this.name});

  General.fromJson(Map<String, dynamic> json) {
    this.serialNumber = json["serial_number"];
    this.name = json["name"];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["serial_number"] = this.serialNumber;
    data["name"] = this.name;
    return data;
  }
}

class Grievance {
  String? serialNumber;
  String? name;

  Grievance({this.serialNumber, this.name});

  Grievance.fromJson(Map<String, dynamic> json) {
    this.serialNumber = json["serial_number"];
    this.name = json["name"];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["serial_number"] = this.serialNumber;
    data["name"] = this.name;
    return data;
  }
}

This is the ModelClass:

class ModelClass with ChangeNotifier {
      List<User> _data = [];
    
      List<User> get data {
        return _data;
      }
    
      Future<void> getData() async {
        final url = Uri.http('192.168.0.6:3007', '/fetchData');
        final response = await http.get(url);
        print(response);
        final List<User> users = userFromJson(response.body);
        print(users);
        _data = users;
        print(_data);
      }
    }

This is the widget MainScreen:

class MainScreen extends StatefulWidget {
  MainScreenState createState() => MainScreenState();
}

class MainScreenState extends State<MainScreen> {
  var clicked = false;

  @override
  void initState() {
    Provider.of<ModelClass>(context, listen: false).getData();
    super.initState();
  }

  void clickedButton() async {
    await Provider.of<ModelClass>(context, listen: false).getData();
    print('clicked');
    setState(() {
      clicked = !clicked;
    });
  }

  ///this field is used to decide if we want to show grievance data only or not
  bool showGrievanceOnly = false;

  @override
  Widget build(BuildContext context) {
    final List<User> usersList = Provider.of<ModelClass>(context).data;

    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo App"),
      ),
      body: !clicked
          ? Center(
              child: ElevatedButton(
                  child: Text('Click Me'), onPressed: clickedButton))
          :
          // ListView.builder(
          //   itemBuilder: (context, index) =>
          //       Row(
          //         children: [
          //           Text(usersList[0].wardNo![0].grievance![index].serialNumber!), //*
          //           SizedBox(width: 10),
          //           Text(usersList[0].wardNo![0].grievance![index].name!)  //*
          //         ],
          //       ),
          //   itemCount: usersList[0].wardNo![0].grievance!.length,
          //
          // )

          ListView.builder(
              itemBuilder: (context, index) => Column(
                children: [
                  if (usersList[index].wardNo != null) ...[
                    for (WardNo ward in usersList[index].wardNo!) ...[
                      if (ward.grievance != null) ...[
                        for (Grievance grievance in ward.grievance!) ...[
                          Row(
                            children: [
                              Text(grievance.serialNumber ?? ''), //*
                              SizedBox(width: 10),
                              Text(grievance.name ?? ''), //*
                            ],
                          ),
                        ],
                      ],
                      if (!showGrievanceOnly && ward.general != null) ...[
                        for (General general in ward.general!) ...[
                          Row(
                            children: [
                              Text(general.serialNumber ?? ''), //*
                              SizedBox(width: 10),
                              Text(general.name ?? ''), //*
                            ],
                          ),
                        ],
                      ],
                    ]
                  ]
                ],
              ),
              itemCount: usersList.length,
            ),
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM