raj
raj

Reputation: 341

Dropdown in flutter from LIST

Displaying the data from my API based on the Dropdown selected value. I want to display on the same page. The data from the server(response) is displaying on the console. But still, this data is not displaying. import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;

//import 'package:json_parsing_example/model2.dart';
//import 'package:json_parsing_example/models.dart'

List<YouModel> youModelFromJson(String str) => List<YouModel>.from(json.decode(str).map((x) => YouModel.fromJson(x)));

String youModelToJson(List<YouModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class YouModel {
    String columnName;

    YouModel({
        this.columnName,
    });

    factory YouModel.fromJson(Map<String, dynamic> json) => YouModel(
        columnName: json["column_name"],
    );

    Map<String, dynamic> toJson() => {
        "column_name": columnName,
    };
}

UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));

String userModelToJson(UserModel data) => json.encode(data.toJson());

class UserModel {
    String username;
    String name;

    UserModel({
        this.username,
        this.name,
    });

    factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
        username: json["username"],
        name: json["Name"],
    );

    Map<String, dynamic> toJson() => {
        "username": username,
        "Name": name,
    };
}
class Addoffers2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _Addoffers2State();
}
class _Addoffers2State extends State<Addoffers2> {
  List<String> _companies = [];
  bool _isLoading = false;

  String _selectedCompany;
  @override
  void initState() {
    super.initState();
    _selectedCompany=null;
    _getcompanylist();
  }

  Future<String> loadFromAssets() async {
    return await rootBundle.loadString('json/parse.json');
  }

  _getcompanylist() async {
    setState(() {
      _isLoading = true;
    });
    print("getting..");
    final responseStr =
        await http.get('http://10.0.2.2/Flutter/GetCompanieslist.php'); 
         //String responseStr = await loadFromAssets();


         final listData = youModelFromJson(responseStr.body);
         for(int i=0;i<listData.length;i++)
         {
           print('this is the list :'+listData[i].columnName);
          // _companies.add(listData[i].columnName);
         }

         // above method is the standard method to get creating a model class and then get the list of strings
         // I have just shown you but example is according to you code . 

         // this above loadFromAssets is that you hit the api and you get the json string response 
         // i have created a dummy json file where i can the String.


         // Else everything is the same as below you just have to pass the response.body to the json.decode method.

    var jsonData = json.decode(responseStr.body);

    for (var u in jsonData) {
      _companies.add(u.toString().substring(14, u.toString().length - 1));
    }

    for (int i = 0; i < _companies.length; i++) {
      print(_companies[i].toString());
    }
    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
//double width = MediaQuery.of(context).size.width;
    //double height = MediaQuery.of(context).size.height;
    return MaterialApp(
      //color: Colors.red,
      home: Scaffold(
          backgroundColor: Colors.red,
          appBar: AppBar(
            backgroundColor: Theme.of(context).backgroundColor,
            title: Text("Add.."),
          ),
          body: Container(
            color: Colors.blue,
            // just put your height i have modified it replace it by height / 8
            child: _isLoading
                ? CircularProgressIndicator()
                : Center(
                    child: Column(
                    children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Center(
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceAround,
                            children: <Widget>[
                              //MainAxisAlignment: MainAxisAlignment.spaceBetween,
                              Text('Choose..'),
                              DropdownButtonHideUnderline(
                                child: DropdownButton(
                                  // hint: Text('Choose Company'), // Not necessary for Option 1
                                  value: _selectedCompany,
                                  onChanged: (newValue) {
                                    setState(() {
                                      _selectedCompany = newValue;

                                      // here i have taken the boolen variable to show and hide the list if you have not seleted the value from the dropdown the it will show the text and if selected the it will show you the list.
                                    });
                                    print(_selectedCompany);
                                  },
                                  items: _companies.map((company) {
                                    return DropdownMenuItem(
                                      child: new Text(company.toString()),
                                      value: company,
                                    );
                                  }).toList(),
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                      // this is to to check for the initial if string is null then show the text widget.
                      // else if the value is selected then it will show the listview
                      _selectedCompany == null
                          ? Text('Select the dropdown value for list to appear.')// sample text you can modify
                          : Padding(
                              padding: const EdgeInsets.all(0.0),
                              child: Container(
                                height: 100,
                                color: Theme.of(context).backgroundColor,
                                child: new FutureBuilder(
                                    future: _getUsers(
                                        _selectedCompany), // a Future<String> or null
                                    builder: (BuildContext context,
                                        AsyncSnapshot snapshot) {
                                      if (snapshot.connectionState ==
                                          ConnectionState.waiting) {
                                        return Container(
                                            child: Center(
                                          child: new CircularProgressIndicator(
                                            backgroundColor: Colors.white,
                                          ),
                                        ));
                                      }
                                      if (snapshot.hasError) {
                                        return Center(
                                          child: new Text(
                                              'Error ${snapshot.error}'),
                                        );
                                      } else {

                                        return Center(
                                          child: Padding(
                                            padding: const EdgeInsets.fromLTRB(
                                                5.0, 8.0, 5.0, 8.0),
                                            child: ListView.builder(
                                                itemCount: snapshot.data.length,
                                                itemBuilder:
                                                    (BuildContext context,
                                                        int index) {
                                                  List<UserModel> user =
                                                      snapshot.data;

                                                  var username =
                                                      user[index].username;
                                                  var stuname =
                                                      user[index].name;
                                                  print(
                                                      'This is the user name :$username');
                                                  print(
                                                      'This is the name : $stuname');

                                                  //var title=snapshot.data[index]["Title"];
                                                  // new Text(parsedDate.toString());
                                                  return StudentList2(
                                                      regdNo: username,
                                                      name: stuname);
                                                }),
                                          ),
                                        );
                                      }
                                    }),
                              ),
                            ),
                    ],
                  )),
          )),
    );
  }
}

Future<String> loadFromAssets2() async {
  return await rootBundle.loadString('json/parse2.json');
}
// the above method is just for the sample purpose where you get you json String  after hitting the api call for _getUsers method 

Future<List<UserModel>> _getUsers(String selectedcompany) async {
  // here you call you api and you get the response
   var url = 'https://10.0.2.2/Flutter/getstudentdata.php;




    var data = { 'company': selectedcompany};

    // Starting Web Call with data.
    var response = await http.post(url, body: json.encode(data));
print(response.body);
  //String responseStr = await loadFromAssets2();

  final userModel = userModelFromJson(response.body);
  // I have just made the model class for where fromt he below you get the complete object and then added to the list and returned.

  List<UserModel> users = [];

  users.add(userModel);

  print('This is the name : ${users[0].name}'); // Even this also not getting printed



  return users;
}

class StudentList2 extends StatefulWidget {


  final regdNo;
  final name;

  const StudentList2({
    Key key,
    this.regdNo,
    this.name,
  }) : super(key: key);



  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<StudentList2> {
  bool visible = false;

  @override
  Widget build(BuildContext context) {
    print(widget.regdNo.toString());
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5.0),
      child: new Card(
          color: Theme.of(context).primaryColor,
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 2.0),
                child: Container(
                  child: new Text(
                    widget.regdNo.toUpperCase(),
                    style: TextStyle(
                      color: Colors.yellowAccent,
                      fontWeight: FontWeight.bold,
                      fontSize: 15.0,
                    ),
                  ),
                ),
              ),
              ListTile(
                title: new Text(
                  widget.regdNo,
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 14.0,
                  ),
                ),
                subtitle: new Text(
                  (widget.name),
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 15.0,
                  ),
                ),
              ),

//
            ],
          )),
    );
  }
}

I am able to retrieve the data from the server and print it on the console. Still, the data is not displaying. I do not know where I did the mistake.

Upvotes: 1

Views: 3422

Answers (2)

Sagar Acharya
Sagar Acharya

Reputation: 3777

So I have completely updated the answer and there are many things that you don't follow according to the global standard.

So I have listed some of the key things that you should follow :

Following is you company list json :

[
    {
        "column_name": "ABC"
    },
    {
        "column_name": "XYZ"
    }
]

Following is the get user json that you will get :

{"username":"1111","Name":"ABC" }

And Later the model class I have create accordingly to the json that you provided and then you can create your own based in the added json.

There are Two model classes that I have created :

First model class is for the company :

// To parse this JSON data, do
//
//     final youModel = youModelFromJson(jsonString);

import 'dart:convert';

List<YouModel> youModelFromJson(String str) => List<YouModel>.from(json.decode(str).map((x) => YouModel.fromJson(x)));

String youModelToJson(List<YouModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class YouModel {
    String columnName;

    YouModel({
        this.columnName,
    });

    factory YouModel.fromJson(Map<String, dynamic> json) => YouModel(
        columnName: json["column_name"],
    );

    Map<String, dynamic> toJson() => {
        "column_name": columnName,
    };
}

second mode class is for the user :

// To parse this JSON data, do
//
//     final userModel = userModelFromJson(jsonString);

import 'dart:convert';

UserModel userModelFromJson(String str) => UserModel.fromJson(json.decode(str));

String userModelToJson(UserModel data) => json.encode(data.toJson());

class UserModel {
    String username;
    String name;

    UserModel({
        this.username,
        this.name,
    });

    factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
        username: json["username"],
        name: json["Name"],
    );

    Map<String, dynamic> toJson() => {
        "username": username,
        "Name": name,
    };
}

Below is the main ui file just Check the comments that I have made so that it will be helpful for you .

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:json_parsing_example/model2.dart';
import 'package:json_parsing_example/models.dart';


void main() => runApp(Addoffers());

class Addoffers extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _AddoffersState();
}

class _AddoffersState extends State<Addoffers> {
  List<String> _companies = [];
  bool _isLoading = false;

  String _selectedCompany;
  @override
  void initState() {
    super.initState();
    _selectedCompany=null;
    _getcompanylist();
  }

  Future<String> loadFromAssets() async {
    return await rootBundle.loadString('json/parse.json');
  }

  _getcompanylist() async {
    setState(() {
      _isLoading = true;
    });
    print("getting..");
    /* final response =
        await http.get('http://10.0.2.2/Flutter/GetCompanieslist.php'); */
         String responseStr = await loadFromAssets();


         final listData = youModelFromJson(responseStr);
         for(int i=0;i<listData.length;i++)
         {
           print('this is the list :'+listData[i].columnName);
          // _companies.add(listData[i].columnName);
         }

         // above method is the standard method to get creating a model class and then get the list of strings
         // I have just shown you but example is according to you code . 

         // this above loadFromAssets is that you hit the api and you get the json string response 
         // i have created a dummy json file where i can the String.


         // Else everything is the same as below you just have to pass the response.body to the json.decode method.

    var jsonData = json.decode(responseStr);

    for (var u in jsonData) {
      _companies.add(u.toString().substring(14, u.toString().length - 1));
    }

    for (int i = 0; i < _companies.length; i++) {
      print(_companies[i].toString());
    }
    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
//double width = MediaQuery.of(context).size.width;
    //double height = MediaQuery.of(context).size.height;
    return MaterialApp(
      //color: Colors.red,
      home: Scaffold(
          backgroundColor: Colors.red,
          appBar: AppBar(
            backgroundColor: Theme.of(context).backgroundColor,
            title: Text("Add.."),
          ),
          body: Container(
            color: Colors.blue,
            // just put your height i have modified it replace it by height / 8
            child: _isLoading
                ? CircularProgressIndicator()
                : Center(
                    child: Column(
                    children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Center(
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceAround,
                            children: <Widget>[
                              //MainAxisAlignment: MainAxisAlignment.spaceBetween,
                              Text('Choose..'),
                              DropdownButtonHideUnderline(
                                child: DropdownButton(
                                  // hint: Text('Choose Company'), // Not necessary for Option 1
                                  value: _selectedCompany,
                                  onChanged: (newValue) {
                                    setState(() {
                                      _selectedCompany = newValue;

                                      // here i have taken the boolen variable to show and hide the list if you have not seleted the value from the dropdown the it will show the text and if selected the it will show you the list.
                                    });
                                    print(_selectedCompany);
                                  },
                                  items: _companies.map((company) {
                                    return DropdownMenuItem(
                                      child: new Text(company.toString()),
                                      value: company,
                                    );
                                  }).toList(),
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                      // this is to to check for the initial if string is null then show the text widget.
                      // else if the value is selected then it will show the listview
                      _selectedCompany == null
                          ? Text('Select the dropdown value for list to appear.')// sample text you can modify
                          : Padding(
                              padding: const EdgeInsets.all(0.0),
                              child: Container(
                                height: 100,
                                color: Theme.of(context).backgroundColor,
                                child: new FutureBuilder(
                                    future: _getUsers(
                                        _selectedCompany), // a Future<String> or null
                                    builder: (BuildContext context,
                                        AsyncSnapshot snapshot) {
                                      if (snapshot.connectionState ==
                                          ConnectionState.waiting) {
                                        return Container(
                                            child: Center(
                                          child: new CircularProgressIndicator(
                                            backgroundColor: Colors.white,
                                          ),
                                        ));
                                      }
                                      if (snapshot.hasError) {
                                        return Center(
                                          child: new Text(
                                              'Error ${snapshot.error}'),
                                        );
                                      } else {

                                        return Center(
                                          child: Padding(
                                            padding: const EdgeInsets.fromLTRB(
                                                5.0, 8.0, 5.0, 8.0),
                                            child: ListView.builder(
                                                itemCount: snapshot.data.length,
                                                itemBuilder:
                                                    (BuildContext context,
                                                        int index) {
                                                  List<UserModel> user =
                                                      snapshot.data;

                                                  var username =
                                                      user[index].username;
                                                  var stuname =
                                                      user[index].name;
                                                  print(
                                                      'This is the user name :$username');
                                                  print(
                                                      'This is the name : $stuname');

                                                  //var title=snapshot.data[index]["Title"];
                                                  // new Text(parsedDate.toString());
                                                  return StudentList2(
                                                      regdNo: username,
                                                      name: stuname);
                                                }),
                                          ),
                                        );
                                      }
                                    }),
                              ),
                            ),
                    ],
                  )),
          )),
    );
  }
}

Future<String> loadFromAssets2() async {
  return await rootBundle.loadString('json/parse2.json');
}
// the above method is just for the sample purpose where you get you json String  after hitting the api call for _getUsers method 

Future<List<UserModel>> _getUsers(String selectedcompany) async {
  /* var data = await http.post("http://10.0.2.2/Flutter/getstdata.php", body: {
    "company": selectedcompany,
    //print(data.body);
  }); */
  // here you call you api and you get the response

  String responseStr = await loadFromAssets2();

  final userModel = userModelFromJson(responseStr);
  // I have just made the model class for where fromt he below you get the complete object and then added to the list and returned.

  List<UserModel> users = [];

  users.add(userModel);

  print('This is the name : ${users[0].name}');

//final x=users.length.toString();
  //debugPrint("records:" + users.length.toString());
  //debugPrint("kkk:" + absentees.length.toString());

  return users;
}

class StudentList2 extends StatefulWidget {
  //MyHomePage(String branch);

  final regdNo;
  final name;

  const StudentList2({
    Key key,
    this.regdNo,
    this.name,
  }) : super(key: key);

  //final String branch;

  //const StudentList({Key key, this.branch}) : super(key: key);
  //MyHomePage(String branch);

  //  final String title;
  // final String branch="";
  // MyHomePage(String branch, {Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<StudentList2> {
  bool visible = false;
//bool _btnEnabled = false;
  //bool _validate = false;
  // var _firstPress = true ;

  //Color _iconColor = Colors.yellow;
  //Color _iconColor2 = Colors.white;

  //var poll;

  //DateTime parsedDate;

  @override
  Widget build(BuildContext context) {
    print(widget.regdNo.toString());
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5.0),
      child: new Card(
          color: Theme.of(context).primaryColor,
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 2.0),
                child: Container(
                  child: new Text(
                    widget.regdNo.toUpperCase(),
                    style: TextStyle(
                      color: Colors.yellowAccent,
                      fontWeight: FontWeight.bold,
                      fontSize: 15.0,
                    ),
                  ),
                ),
              ),
              ListTile(
                title: new Text(
                  widget.regdNo,
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 14.0,
                  ),
                ),
                subtitle: new Text(
                  (widget.name),
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 15.0,
                  ),
                ),
              ),

//
            ],
          )),
    );
  }
}


// This is not the good approach to create a model class just check the sample model class that i have created. 
class User {
  //final int index;
  final String username;
  final String name;

  //final Float cgpa;

  User(
    this.username,
    this.name,
  );
}

And below is the sample Gif file for you :

enter image description here

Upvotes: 1

Chris Papantonis
Chris Papantonis

Reputation: 739

As stated by @pskink the method _getcompanylist() is async. An async function runs asynchronously, which means that the rest of the program doesn't wait for it to complete. You can use a future builder to deal whit that or you can simply wait for it by using the await function. I believe that for your code snippet future builder is the better choice.

Upvotes: 0

Related Questions