How to display items from a list of maps into a listview

1,322

Edit: Updated the answer to utilize the serializer OP provided and utilize stateful widget.

Please note in the following code the data is constant but you have adapt it to handle the async http request, as i would like to show the answer in a dartpad here.

import 'package:flutter/material.dart';
import 'dart:convert';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MainWidget());
}

class MainWidget extends StatelessWidget {
  @override
  Widget build(context) {
    return MaterialApp(home: Scaffold(body: Questions()));
  }
}

class Questions extends StatefulWidget {
  @override
  _QuestionsPageState createState() => _QuestionsPageState();
}

class _QuestionsPageState extends State<Questions> {
  QuestionModel data;
  var users;

  String url =
      'https://90d53c1e-1ca3-4d5e-982e-0ff81a3ba7f5.mock.pstmn.io/profile/questions';

  requestQuestionsAPI() {
//   final response = await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});

    setState(() {
      //data = json.decode(response.body);

      // Isntead of http fecth a constant data
      data = questionModelFromJson('''{
  "body": {
    "System Topics": [
      {"Topic ID": "2", "Title": "Tres", "Description": "Dos"},
      {"Topic ID": "3", "Title": "Pls Work", "Description": "nfewtrwe"},
      {"Topic ID": "4", "Title": "Juice", "Description": "Bar"}
    ],
    "Video Requests": [
      {
        "Topic ID": "1",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What's you first christmas like?",
        "Description": "Please tell me about your Christmas?"
      },
      {
        "Topic ID": "4",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": ""
      },
      {
        "Topic ID": "5",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": ""
      },
      {
        "Topic ID": "6",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": ""
      },
      {
        "Topic ID": "7",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": ""
      },
      {
        "Topic ID": "8",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": ""
      },
      {
        "Topic ID": "9",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": "From james"
      },
      {
        "Topic ID": "10",
        "From Name": "New User",
        "From Email": "[email protected]",
        "Title": "What is your name?",
        "Description": "From james"
      }
    ]
  }
}''');
    });
  }

  _questions() {
    requestQuestionsAPI();
  }

  void initState() {
    super.initState();
    _questions();
  }

  dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MyNewWidget(questionModel: data);
  }
}

class MyNewWidget extends StatefulWidget {
  final QuestionModel questionModel;
  MyNewWidget({this.questionModel});
  @override
  _MyNewWidgetState createState() => _MyNewWidgetState();
}

class _MyNewWidgetState extends State<MyNewWidget> {
  @override
  Widget build(BuildContext context) {
    print(widget.questionModel);
    return MyList(
      bodyElement: widget.questionModel.body,
    );
  }
}

class MyList extends StatelessWidget {
  final Body bodyElement;
  MyList({this.bodyElement});
  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Text(
        'Sytem Topics',
        style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 25,
            fontStyle: FontStyle.italic),
      ),
      Divider(),
      Expanded(
        child: ListView.builder(
            shrinkWrap: true,
            itemCount: bodyElement.systemTopics.length,
            itemBuilder: (context, index) {
              return MyListElement(
                id: bodyElement.systemTopics[index].topicId,
                description: bodyElement.systemTopics[index].description,
              );
            }),
      ),
      Text(
        'Video Requests',
        style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 25,
            fontStyle: FontStyle.italic),
      ),
      Divider(),
      Expanded(
        child: ListView.builder(
            shrinkWrap: true,
            itemCount: bodyElement.videoRequests.length,
            itemBuilder: (context, index) {
              return MyListElement(
                id: bodyElement.videoRequests[index].topicId,
                description: bodyElement.videoRequests[index].description,
              );
            }),
      )
    ]);
  }
}

class MyListElement extends StatelessWidget {
  final String id;
  final String description;

  MyListElement({this.id, this.description});

  @override
  Widget build(BuildContext context) {
    print('id is $id');
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(20.0),
      ),
      height: 74.0,
      margin: const EdgeInsets.only(bottom: 10.0),
      child: Row(
        children: <Widget>[
          Container(
            alignment: Alignment.center,
            child: Text(id),
            height: 74.0,
            width: 73.0,
            decoration: BoxDecoration(
              color: Colors.orange,
              borderRadius: BorderRadius.only(
                  topLeft: const Radius.circular(20.0),
                  bottomLeft: const Radius.circular(20.0)),
            ),
          ),
          Container(
            height: 74.0,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                  topRight: const Radius.circular(20.0),
                  bottomRight: const Radius.circular(20.0)),
            ),
            width: 265.0,
            child: Center(
                child: Text(
              description,
              style: TextStyle(fontSize: 24.0, color: Colors.red),
            )),
          )
        ],
      ),
    );
  }
}

/// Serializers

QuestionModel questionModelFromJson(String str) =>
    QuestionModel.fromJson(json.decode(str));

String questionModelToJson(QuestionModel data) => json.encode(data.toJson());

class QuestionModel {
  Body body;

  QuestionModel({
    this.body,
  });

  factory QuestionModel.fromJson(Map<String, dynamic> json) => QuestionModel(
        body: Body.fromJson(json["body"]),
      );

  Map<String, dynamic> toJson() => {
        "body": body.toJson(),
      };
}

class Body {
  List<SystemTopic> systemTopics;
  List<VideoRequest> videoRequests;

  Body({
    this.systemTopics,
    this.videoRequests,
  });

  factory Body.fromJson(Map<String, dynamic> json) => Body(
        systemTopics: List<SystemTopic>.from(
            json["System Topics"].map((x) => SystemTopic.fromJson(x))),
        videoRequests: List<VideoRequest>.from(
            json["Video Requests"].map((x) => VideoRequest.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "System Topics":
            List<dynamic>.from(systemTopics.map((x) => x.toJson())),
        "Video Requests":
            List<dynamic>.from(videoRequests.map((x) => x.toJson())),
      };
}

class SystemTopic {
  String topicId;
  String title;
  String description;

  SystemTopic({
    this.topicId,
    this.title,
    this.description,
  });

  factory SystemTopic.fromJson(Map<String, dynamic> json) => SystemTopic(
        topicId: json["Topic ID"],
        title: json["Title"],
        description: json["Description"],
      );

  Map<String, dynamic> toJson() => {
        "Topic ID": topicId,
        "Title": title,
        "Description": description,
      };
}

class VideoRequest {
  String topicId;
  String fromName;
  String fromEmail;
  String title;
  String description;

  VideoRequest({
    this.topicId,
    this.fromName,
    this.fromEmail,
    this.title,
    this.description,
  });

  factory VideoRequest.fromJson(Map<String, dynamic> json) => VideoRequest(
        topicId: json["Topic ID"],
        fromName: json["From Name"],
        fromEmail: json["From Email"],
        title: json["Title"],
        description: json["Description"],
      );

  Map<String, dynamic> toJson() => {
        "Topic ID": topicId,
        "From Name": fromName,
        "From Email": fromEmail,
        "Title": title,
        "Description": description,
      };
}

The corresponding output is as shown below.

enter image description here

Share:
1,322
frax
Author by

frax

Updated on December 18, 2022

Comments

  • frax
    frax over 1 year

    I don't know how to display the values of Topic ID from either the System Topics or Video Requests.

    I am getting the source from a http request to this url: https://public.free.beeceptor.com/api

    The following is the response.

    {
        "body": {
            "System Topics": [
                {
                    "Topic ID": "2",
                    "Title": "Tres",
                    "Description": "Dos"
                },
                {
                    "Topic ID": "3",
                    "Title": "Pls Work",
                    "Description": "nfewtrwe"
                },
                {
                    "Topic ID": "4",
                    "Title": "Juice",
                    "Description": "Bar"
                }
            ],
            "Video Requests": [
                {
                    "Topic ID": "1",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What's you first christmas like?",
                    "Description": "Please tell me about your Christmas?"
                },
                {
                    "Topic ID": "4",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": ""
                },
                {
                    "Topic ID": "5",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": ""
                },
                {
                    "Topic ID": "6",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": ""
                },
                {
                    "Topic ID": "7",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": ""
                },
                {
                    "Topic ID": "8",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": ""
                },
                {
                    "Topic ID": "9",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": "From james"
                },
                {
                    "Topic ID": "10",
                    "From Name": "New User",
                    "From Email": "[email protected]",
                    "Title": "What is your name?",
                    "Description": "From james"
                }
            ]
        }
    }
    

    I want to display the values into a listview like so but directly from the https stream.

    
    Container(
                    width: 338,
                    height: 500.0,
                    child: ListView.builder(
                      itemCount: data == null ? 0 : data.length,
                      itemBuilder: (context, i) {
                        return Container(
                          decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.circular(20.0),
                          ),
                          height: 74.0,
                          margin: const EdgeInsets.only(bottom: 10.0),
                          width: MediaQuery.of(context).size.width,
                          child: Row(
                            children: <Widget>[
                              Container(
                                child: Text(data[i]["System Topics"]["Topic ID"]),
                                height: 74.0,
                                width: 73.0,
                                decoration: BoxDecoration(
                                  color: Colors.orange,
                                  borderRadius: BorderRadius.only(
                                      topLeft: const Radius.circular(20.0),
                                      bottomLeft: const Radius.circular(20.0)),
                                ),
                              ),
                              Container(
                                height: 74.0,
                                decoration: BoxDecoration(
                                  color: Colors.white,
                                  borderRadius: BorderRadius.only(
                                      topRight: const Radius.circular(20.0),
                                      bottomRight: const Radius.circular(20.0)),
                                ),
                                width: 265.0,
                                child: Center(
                                    child: Text(
                                  data[i],
                                  style:
                                      TextStyle(fontSize: 24.0, color: maincolor),
                                )),
                              )
                            ],
                          ),
                        );
                      },
                    ),
                  ),
    

    I've already parsed the JSON but when I try using it as an object like this:

    Text(questions[i].body.systemTopics.topicid)

    It doesn't let me. If I do this however: questions[i].body.systemTopics then it won't throw an error

    • Yuu Woods
      Yuu Woods about 4 years
      How did you parse the json? I think you need to parse to class.
    • Abhilash Chandran
      Abhilash Chandran about 4 years
      If you can set up a minimum reproducible code in dartpad, we can help you fix it.
  • frax
    frax about 4 years
    Thank you for the answer, but how would this work for StatefulWidgets? I need them because the json data is retrieved from an api
  • Abhilash Chandran
    Abhilash Chandran about 4 years
    You have to write a json serializer for the incoming json if you need one. There are good resources on how to do simple json serialization like this and if your api has more complex structure with code generators like this. The current approach will work for StatefulWidget as it is.
  • Abhilash Chandran
    Abhilash Chandran about 4 years
    So you have already written serializer. You could have posted it earlier would have been helpful. :) Anyway, in order to access the instance variable of a stateful widget you need use it like widget.data and widget.myvariable etc. I will see If I can come with the same solution with the stateful widget but this time using your serializer.
  • Abhilash Chandran
    Abhilash Chandran about 4 years
    Is the ui result shown above what you expected or is it something else.?
  • Abhilash Chandran
    Abhilash Chandran about 4 years
    I hope this helps. If this doesn't solve your issue, then I would suggest to edit the question to focus what exactly you need.