Flutter Nested array? - json

I have these JSON data
[
{
"student_id": 1,
"studentid": 1204,
"password": "demo",
"name": "Amber",
"level": "student",
"course_name": [
"Math",
"History"
]
}
]
Kindly show me the code to to achieve this :

Actually you have a JSON array (only one index), should be something like:
myArray[0].course_name.forEach(course => console.log(course));

data[index].courseName[0]
https://app.quicktype.io/ for right "model"
model.dart
// To parse this JSON data, do
//
// final welcome = welcomeFromJson(jsonString);
import 'dart:convert';
List<Welcome> welcomeFromJson(String str) => List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));
String welcomeToJson(List<Welcome> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Welcome {
int studentId;
int studentid;
String password;
String name;
String level;
List<String> courseName;
Welcome({
this.studentId,
this.studentid,
this.password,
this.name,
this.level,
this.courseName,
});
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
studentId: json["student_id"] == null ? null : json["student_id"],
studentid: json["studentid"] == null ? null : json["studentid"],
password: json["password"] == null ? null : json["password"],
name: json["name"] == null ? null : json["name"],
level: json["level"] == null ? null : json["level"],
courseName: json["course_name"] == null ? null : List<String>.from(json["course_name"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"student_id": studentId == null ? null : studentId,
"studentid": studentid == null ? null : studentid,
"password": password == null ? null : password,
"name": name == null ? null : name,
"level": level == null ? null : level,
"course_name": courseName == null ? null : List<dynamic>.from(courseName.map((x) => x)),
};
}
main.dart
var jsonString = [
{
"student_id": 1,
"studentid": 1204,
"password": "demo",
"name": "Amber",
"level": "student",
"course_name": ["Math", "History"]
}
];
List<Welcome> hui = welcomeFromJson(json.encode(jsonString));
print(hui[0].courseName[0]);

Try this now
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(new MaterialApp(
home: new HomePage(),
));
}
class HomePage extends StatefulWidget {
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage> {
List data;
bool isLoading = false;
Future<String> getData({isShowLoading: true}) async {
// refreshKey.currentState?.show(atTop: false);
//await Future.delayed(Duration(seconds: 2));
if (isShowLoading) {
setState(() {
isLoading = true;
});
}
var response = await http.get(
Uri.encodeFull("https://ikns.info/api/nested-array.php"),
headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
if (isShowLoading) {
setState(() {
isLoading = false;
});
}
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
if (mounted) {
setState(() {
data = jsonDecode(response.body);
});
}
return "Success!";
}
var refreshKey = GlobalKey<RefreshIndicatorState>();
#override
void initState() {
super.initState();
this.getData();
}
Future<Null> _onRefresh() async {
await getData(isShowLoading: false);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Parsing List of Strings"),
),
body: isLoading
? Center(
child: Text('Loading...'),
)
: RefreshIndicator(
key: refreshKey,
child: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
List<dynamic> items = data[index]["course_name"];
return GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => DetailsPage(
todo: Todo.fromJson(data[index]),
),
),
);
},
child: new Card(
child: Column(
children: <Widget>[
Container(
child: new Text(data[index]["name"]),
),
Column(
children: List.generate(items.length, (index) {
return Text(
"${items[index]}",
style: TextStyle(color: Colors.red),
);
}),
),
],
),
),
);
},
),
onRefresh: _onRefresh,
),
);
}
}
class Todo {
final String name;
Todo(this.name);
Todo.fromJson(Map<String, dynamic> json) : name = json['name'];
}
class DetailsPage extends StatelessWidget {
final Todo todo;
DetailsPage({Key key, #required this.todo}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text(todo.name),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Text(todo.name),
),
);
}
}
UPDATE
OnClick Math, pass Math to the other screen (same for history)
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(new MaterialApp(
home: new HomePage(),
));
}
class HomePage extends StatefulWidget {
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage> {
List data;
bool isLoading = false;
Future<String> getData({isShowLoading: true}) async {
// refreshKey.currentState?.show(atTop: false);
//await Future.delayed(Duration(seconds: 2));
if (isShowLoading) {
setState(() {
isLoading = true;
});
}
var response = await http.get(
Uri.encodeFull("https://ikns.info/api/nested-array.php"),
headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
if (isShowLoading) {
setState(() {
isLoading = false;
});
}
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
if (mounted) {
setState(() {
data = jsonDecode(response.body);
});
}
return "Success!";
}
var refreshKey = GlobalKey<RefreshIndicatorState>();
#override
void initState() {
super.initState();
this.getData();
}
Future<Null> _onRefresh() async {
await getData(isShowLoading: false);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Parsing List of Strings"),
),
body: isLoading
? Center(
child: Text('Loading...'),
)
: RefreshIndicator(
key: refreshKey,
child: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
List<dynamic> items = data[index]["course_name"];
return new Card(
child: Column(
children: <Widget>[
Container(
child: new Text(data[index]["name"]),
),
Column(
children: List.generate(items.length, (index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => DetailsPage(
todo: Todo(items[index].toString()),
),
),
);
},
child: Text(
"${items[index]}",
style: TextStyle(color: Colors.red),
),
);
}),
),
],
),
);
},
),
onRefresh: _onRefresh,
),
);
}
}
class Todo {
final String name;
Todo(this.name);
Todo.fromJson(Map<String, dynamic> json) : name = json['name'];
}
class DetailsPage extends StatelessWidget {
final Todo todo;
DetailsPage({Key key, #required this.todo}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text(todo.name),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Text(todo.name),
),
);
}
}

Related

Fetch data from multiple api but display it in the same future builder

So I have multiple API but I can't display the data in the same future builder. Does anyone know what is going on?
Future<List> fetchData() async {
String url = 'someAPI';
final preferences = await SharedPreferences.getInstance();
final key = 'token';
final value = preferences.get(key);
var response = await http.get(Uri.parse(url), headers: {
'Conten-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $value '
});
log(response.body);
if (response.statusCode == 200) {
return [
// Album.fromJson(jsonDecode(response.body)),
for (final item in jsonDecode(response.body)) Album.fromJson(item),
];
} else {
throw Exception('Failed to load album');
}
}
Future<List> fetchDataDetail(String id) async {
String url2 = 'someAPI2' + id;
final preferences = await SharedPreferences.getInstance();
final key = 'token';
final value = preferences.get(key);
var response2 = await http.get(Uri.parse(url2), headers: {
'Conten-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $value '
});
log(response2.body);
if (response2.statusCode == 200) {
return [
// ReadData.fromJson(jsonDecode(response2.body)),
for (final item in jsonDecode(response2.body)) ReadData.fromJson(item),
// List<Map<String, dynamic>>.from(json.decode(response2.body)[ReadData])
];
} else {
throw Exception('Failed to load album');
}
}`
This is my UI for displaying the data that I fetch
class EmployeeList extends StatefulWidget {
const EmployeeList({Key? key}) : super(key: key);
static String id = 'employee';
#override
State<EmployeeList> createState() => _EmployeeListState();
}
class _EmployeeListState extends State<EmployeeList> {
late Future<List> futureAlbum;
late Future<List> futureReadData;
List<Album>? album;
List<ReadData>? readData;
#override
void initState() {
super.initState();
futureAlbum = fetchData();
futureReadData = fetchDataDetail(toString());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Daftar Pegawai'),
backgroundColor: Color(0xFFF8B400),
),
body: SafeArea(
child: FutureBuilder<List>(
future: Future.wait([futureAlbum, futureReadData]),
initialData: [],
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView(
children: [
ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) => ListTile(
onTap: (() {
print('${snapshot.data![index].Personal}');
}),
leading: CircleAvatar(
backgroundColor: Colors.blue,
),
title: Row(
children: [
Expanded(
child: Text('${snapshot.data![index].namaLengkap}'),
),
SizedBox(width: 25),
Expanded(
child: Text('${snapshot.data![index].id}'),
),
],
),
),
),
],
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Center(
child: CircularProgressIndicator(),
);
},
),
),
);
}
}
This is the class from 1st API
class Album {
Album({
required this.id,
required this.namaLengkap,
});
int? id;
String? namaLengkap;
factory Album.fromJson(Map<String, dynamic> json) => Album(
id: json["id"],
namaLengkap: json["nama_lengkap"],
);
Map<String, dynamic> toJson() => {
"id": id,
"nama_lengkap": namaLengkap,
};
}
This is the class from the 2nd API
class ReadData {
ReadData({
required this.personal,
required this.riwayat,
});
Personal personal;
List<Riwayat> riwayat;
factory ReadData.fromJson(Map<String, dynamic> json) => ReadData(
personal: Personal.fromJson(json["personal"]),
riwayat:
List<Riwayat>.from(json["riwayat"].map((x) => Riwayat.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"personal": personal.toJson(),
"riwayat": List<dynamic>.from(riwayat.map((x) => x.toJson())),
};
}
Also, this is the error message
Exception has occurred.
_TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable')
This error appeared in the second API when I tried to return it.

Show nested JSON from API in single Page with multiple lists

Im new in Flutter and i'm struggeling with a nested JSON from API which data i want to show in one single page.
I get this JSON from a URL and decode it in a class, which is working fine:
{
"service1": [
{
"firstname": "Peter",
"lastname": "Smith"
},
{
"firstname": "Paul",
"lastname": "Johnson"
}
],
"service2": [
{
"firstname": "Mary",
"lastname": "Williams"
},
{
"firstname": "Guy",
"lastname": "Brown"
}
]
}
Classes:
/*------------------------------
staff.dart
------------------------------*/
import 'dart:convert';
class Staff {
String? service;
String? firstname;
String? lastname;
Staff({this.service, this.firstname, this.lastname});
factory Staff.fromMap(Map<String, dynamic> data) => Staff(
service: data['service'] as String?,
firstname: data['firstname'] as String?,
lastname: data['lastname'] as String?,
);
Map<String, dynamic> toMap() => {
'service': '',
'firstname': firstname,
'lastname': lastname,
};
/// Parses the string and returns the resulting Json object.
factory Staff.fromJson(String data) {
return Staff.fromMap(json.decode(data) as Map<String, dynamic>);
}
/// Converts [Staff] to a JSON string.
String toJson() => json.encode(toMap());
}
/*------------------------------
servicedesk.dart
------------------------------*/
import 'dart:convert';
import 'staff.dart';
class ServiceDesk {
List<Staff>? service1;
List<Staff>? service2;
ServiceDesk({
this.service1,
this.service2,
});
factory ServiceDesk.fromMap(Map<String, dynamic> data) => ServiceDesk(
service1: (data['service1'] as List<dynamic>?)
?.map((e) => Staff.fromMap(e as Map<String, dynamic>))
.toList(),
service2: (data['service2'] as List<dynamic>?)
?.map((e) => Staff.fromMap(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> toMap() => {
'service1': service1?.map((e) => e.toMap()).toList(),
'service2': service2?.map((e) => e.toMap()).toList(),
};
/// Parses the string and returns the resulting Json object as [ServiceDesk].
factory ServiceDesk.fromJson(String data) {
var object = ServiceDesk.fromMap(json.decode(data) as Map<String, dynamic>);
object.b1!.insert(0, Staff(service: 'Title for Service1'));
object.b2!.insert(0, Staff(service: 'Title for Service2'));
return object;
}
/// Converts to a JSON string.
String toJson() => json.encode(toMap());
}
That's the code i have (Pseudocode between):
// PSEUDOCODE!!
Widget ListWithService(List<Staff>? entry) {
return ListView.builder(
itemCount: entry!.length,
padding: const EdgeInsets.all(2.0),
itemBuilder: (context, position) {
final item = entry[position];
if (item.service != null) {
return ListTile(
title: Text(
'${item.service}',
style: Theme.of(context).textTheme.headline5,
),
);
} else {
return ListTile(
title: Text(
'${item.firstname} ${item.lastname}',
style: Theme.of(context).textTheme.bodyText1,
),
);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Service Desk'),
),
body: FutureBuilder<sdclass.ServiceDesk>(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasData == true) {
return [
ListWithService(snapshot.data.service1),
ListWithSercice(snapshot.data.service1);
] // PSEUDOCODE!!
} else if (snapshot.hasError) {
return const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
}
),
);
}
What i would have at the end should look like this on the full page:
Title for Service1 (Headline)
Peter Smith
Paul Johnson
Title for Service2 (Headline)
Mary Williams
Guy Brown
Could someone help me with the code to get it work?
Update Code
Thanks for your updated example. I tested it in my code. First, everything looks fine. But wenn i switch to the screen with the json, i get a error:
Expected a value of type 'FutureOr<Map<String, List<Map<String, String>>>>', but got one of type '_JsonMap'
import 'dart:convert';
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class ServiceDesk extends StatelessWidget {
const ServiceDesk({Key? key}) : super(key: key);
Future<Map<String, List<Map<String, String>>>> getData() async {
String link = "https://url-to-json-file.json";
final res = await http
.get(Uri.parse(link), headers: {"Accept": "application/json"});
if (res.statusCode == 200) {
var utf8decoded = utf8.decode(res.body.toString().codeUnits);
var decoded = json.decode(utf8decoded);
return decoded;
} else {
throw Exception('Failed to load JSON');
}
}
Widget listViewWidget(
Iterable<MapEntry<String, List<Map<String, String>>>> entries) {
return ListView.builder(
itemCount: entries.length,
padding: const EdgeInsets.all(2.0),
itemBuilder: (context, index) {
final entry = entries.elementAt(index);
final key = entry.key;
final values = entry.value;
return Column(
children: [
ListTile(
title: Text(
'Title for $key',
style: Theme.of(context).textTheme.headline5,
),
),
for (var person in values)
ListTile(
title: Text(
'${person["firstname"]} ${person["lastname"]}',
style: Theme.of(context).textTheme.bodyText1,
),
),
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Service Desk'),
),
body: FutureBuilder(
future: getData(),
builder: (_,
AsyncSnapshot<Map<String, List<Map<String, String>>>> snapshot) {
if (snapshot.hasData == true) {
final entries = snapshot.data?.entries ?? {};
return listViewWidget(entries);
} else if (snapshot.hasError) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Text("Fehler: ${snapshot.error}"),
],
));
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
}),
);
}
}
In the Dart language, you can use for loop in the list, it makes it easier to work with Flutter UI.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:convert';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const RootView(),
);
}
}
class RootView extends StatelessWidget {
const RootView({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
child: const Text('GO TO SAFF SERVICE'),
onPressed: () {
Navigator.push(context, Home.route());
},
),
),
);
}
}
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
static Route route() {
return CupertinoPageRoute(builder: (_) => const Home());
}
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
late Future<StaffService> staffService;
#override
void initState() {
staffService = getStaffService();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Services')),
body: Center(
child: FutureBuilder<StaffService>(
future: staffService,
builder: (_, snapshot) {
if (snapshot.hasData) {
final saff = snapshot.data!;
return ListView(
children: [
if (saff.service1.isNotEmpty)
StaffServiceTile(
title: Text(
'Title for Service 1',
style: Theme.of(context).textTheme.headline5,
),
services: saff.service1,
),
if (saff.service2.isNotEmpty)
StaffServiceTile(
title: Text(
'Title for Service 2',
style: Theme.of(context).textTheme.headline5,
),
services: saff.service2,
),
],
);
} else if (snapshot.hasError) {
return const Text('Error on loaad data. Try again later.');
} else {
return const CircularProgressIndicator();
}
},
),
),
);
}
}
class StaffServiceTile extends StatelessWidget {
const StaffServiceTile({
Key? key,
required this.title,
required this.services,
}) : super(key: key);
final Widget title;
final List<Service> services;
#override
Widget build(BuildContext context) {
return Column(
children: [
ListTile(title: title),
for (var person in services)
ListTile(
title: Text(
'${person.firstname} ${person.lastname}',
),
),
],
);
}
}
class StaffService {
StaffService({this.service1 = const [], this.service2 = const []});
List<Service> service1, service2;
factory StaffService.fromJson(String str) {
return StaffService.fromMap(json.decode(str));
}
String toJson() => json.encode(toMap());
factory StaffService.fromMap(Map<String, dynamic> json) => StaffService(
service1: List<Service>.from(json["service1"].map((x) => Service.fromMap(x))),
service2: List<Service>.from(json["service2"].map((x) => Service.fromMap(x))),
);
Map<String, dynamic> toMap() => {
"service1": List<dynamic>.from(service1.map((x) => x.toMap())),
"service2": List<dynamic>.from(service2.map((x) => x.toMap())),
};
}
class Service {
Service({this.firstname, this.lastname});
String? firstname, lastname;
factory Service.fromJson(String str) => Service.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory Service.fromMap(Map<String, dynamic> json) => Service(
firstname: json["firstname"],
lastname: json["lastname"],
);
Map<String, dynamic> toMap() => {
"firstname": firstname,
"lastname": lastname,
};
}
Future<StaffService> getStaffService() async {
await Future.delayed(const Duration(seconds: 2));
return StaffService.fromMap(data); // <- use fromJson if you load data from the JSON.
}
final data = <String, List<Map<String, String>>>{
"service1": [
{"firstname": "Peter", "lastname": "Smith"},
{"firstname": "Paul", "lastname": "Johnson"}
],
"service2": [
{"firstname": "Mary", "lastname": "Williams"},
{"firstname": "Guy", "lastname": "Brown"}
]
};
Copy and paste in the DartPad to test it.

How to create rows data in to DataTable using from json model json api respons flutter

I am tryieng to fetch json data into the Flutter DataTable. Using Api and employee Model.
I am able to ftech the json data getting from Browser. I am unable to fetch rows into DataTable.
Getting an error below:
LateInitializationError: Field'emps' has not been initialized.
I am facing an issue that unable to getting the values in to the rows. How to call values into the rows. Please help me How to do?
Below is the json data getting from Browser:
[{"empid":1,"empname":"empname","empemail":"email1"},{"empid":2,"empname":"name2","empemail":"email2"},{"empid":3,"empname":"t1","empemail":"e1"},{"empid":7,"empname":"t2","empemail":"e2"}]
Below is the API:
import 'package:http/http.dart' as http;
import 'employees_model.dart';
Future<List> fetchEmployees() async {
Uri url = Uri.parse(" Link ");
final response = await http.get(url);
return employeesFromJson(response.body);
}
Below is employeemodel:
import 'dart:convert';
List<Employees> employeesFromJson(String str) =>
List<Employees>.from(json.decode(str).map((x) => Employees.fromJson(x)));
String employeesToJson(List<Employees> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Employees {
Employees({
required this.id,
required this.name,
required this.email,
});
int id;
String name;
String email;
factory Employees.fromJson(Map<String, dynamic> json) => Employees(
id: json["empid"],
name: json["empname"],
email: json["empemail"],
);
Map<String, dynamic> toJson() => {
"empid": id,
"empname": name,
"empemail": email,
};
}
Below is my example code:
import 'package:flutter/material.dart';
import 'package:webappmysql/employees_model.dart';
import 'package:webappmysql/employees_api.dart';
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
late List<Employees> emps;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Table Example'),
),
body: SingleChildScrollView(
child: DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Email')),
],
rows: emps
.map(
(emp) => DataRow(cells: [
DataCell(
Text(emp.id.toString()),
),
DataCell(
Text(emp.name),
),
DataCell(
Text(emp.email),
),
]),
)
.toList(),
),
),
);
}
}
Future<List<Employee>> fetchResults() async {
List<Employee> _results = [];
var url ="---your link----";
var response = await http.get(url);
if (response.statusCode == 200) {
var resultsJson = json.decode(response.body).cast<Map<String,dynamic>>();
await Future.forEach(resultsJson, (element) {
_results.add(Employee.fromJson(element));
});
}
return Future.value(_results);
}
class Employee {
int? empid;
String? empname;
String? empemail;
Employee({this.empid, this.empname, this.empemail});
Employee.fromJson(Map<String, dynamic> json) {
empid = json['empid'];
empname = json['empname'];
empemail = json['empemail'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['empid'] = this.empid;
data['empname'] = this.empname;
data['empemail'] = this.empemail;
return data;
}
}
class _TestPageState extends State<TestPage> {
late List<Employees> emps;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Table Example'),
),
body: SingleChildScrollView(
child: FutureBuilder<List<Employee>>(
initialData: <Employee>[],
future: fetchResults(),
builder: (context, snapshot) {
if (snapshot.hasError ||
snapshot.data == null ||
snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
return DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Email')),
],
rows: List.generate(
snapshot.data!.length,
(index) {
var emp = snapshot.data![index];
return DataRow(cells: [
DataCell(
Text(emp.empname.toString()),
),
DataCell(
Text(emp.empname),
),
DataCell(
Text(emp.empemail),
),
]);
},
).toList(),
);
},
),
),
);
}
}
I got the solution as below:
The API is:
Future<List<Employees>> fetchResults() async {
Uri url = Uri.parse(" Link ");
var response = await http.get(url);
var resultsJson = json.decode(response.body).cast<Map<String, dynamic>>();
List<Employees> emplist = await resultsJson
.map<Employees>((json) => Employees.fromJson(json))
.toList();
return emplist;
}
The Page Example is:
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Table Example'),
),
body: SingleChildScrollView(
child: Column(
children: [
FutureBuilder<List<Employees>>(
initialData: const <Employees>[],
future: fetchResults(),
builder: (context, snapshot) {
if (snapshot.hasError ||
snapshot.data == null ||
snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
return DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Email')),
],
rows: List.generate(
snapshot.data!.length,
(index) {
var emp = snapshot.data![index];
return DataRow(cells: [
DataCell(
Text(emp.id.toString()),
),
DataCell(
Text(emp.name),
),
DataCell(
Text(emp.email),
),
]);
},
).toList(),
);
},
),
],
),
),
);
}}

There should be exactly one item with [DropdownButton]'s value: Instance of 'Partner'

My dropdown working as expected . but when I selected a item my app crashing with error
There should be exactly one item with [DropdownButton]'s value: Instance of 'Partner'.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
First I declare my variable in class
class _MultipleTestBookingState extends State<MultipleTestBooking> {
Partner? _selectedLab;
Datum? _selectedTest;
....................
declare with Partner?_selectedLab; because my dropdown menu takes in a list of Partners
Then using this variable to show the selected value in my dropdown
Container(
child: FutureBuilder<List<Partner>>(
future: AllPathLab(),
builder:
(BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState !=ConnectionState.done) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Somthing went wrong");
}
if (snapshot.hasData) {
return DropdownButton<Partner>(
value: _selectedLab,
hint: Text("Select Lab"),
items: snapshot.data.map((Partner data) =>
DropdownMenuItem<Partner>(
child: Text("${data.partnerName}"),
value: data,
)
).toList().cast<DropdownMenuItem<Partner>>(),
onChanged: (value){
setState(() {
_selectedLab=value;
encLabId = value!.encPartnerId;
GetTestByLab();
});
}
);
}
return Text("Waiting for Internet Connection");
},
),
),
Full code with my JSON response
So from the data that you provided i have created the code below:
import 'package:date_time_picker/date_time_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/Patner.dart';
import 'package:flutter_app/dataModel.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Partner _selectedLab;
Datum _selectedTest;
Future getAllPathLabResults;
Future getTestByLabResult;
String encLabId = '';
void initState() {
super.initState();
getAllPathLabResults = allPathLab();
getTestByLabResult = getTestByLab();
}
String _selectedDate = DateTime.now().toString();
Future<List<Partner>> allPathLab() async {
String jsonData = jsonstring;
final model = modelFromJson(jsonData);
print("This is the list length : ${model.partner.length}");
List<Partner> arrData = model.partner;
// this Future is for sample as you will be fetching the api data remove this one
Future.delayed(Duration(seconds: 3));
return arrData;
}
Future<List<Datum>> getTestByLab() async {
print("This is the Id :$encLabId");
_selectedTest = null;
var response = await http.post(
Uri.parse("http://medbo.digitalicon.in/api/medboapi/GetTestByLab"),
body: ({"EncId": encLabId}));
if (response.statusCode == 200) {
final dataModel = dataModelFromJson(response.body);
print(dataModel.data.length);
for (final item in dataModel.data) {
print("This is hte test name :${item.testName}");
}
List<Datum> arrData = dataModel.data;
return arrData;
}
return [];
}
#override
Widget build(BuildContext context) {
var screenWidth = MediaQuery.of(context).size.width;
var screenHeight = MediaQuery.of(context).size.height;
var blockSizeHorizontal = (screenWidth / 100);
var blockSizeVertical = (screenHeight / 100);
return Scaffold(
body: SafeArea(
child: Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
title: Text("Booking Information",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 5,
fontFamily: 'Poppins',
color: Theme.of(context).primaryColor,
)),
subtitle: Text("Preferred Visit Date"),
),
),
Container(
margin: EdgeInsets.only(left: 20),
padding: EdgeInsets.only(left: 0, right: 150),
decoration: BoxDecoration(
color: Colors.lightBlue[50],
borderRadius: BorderRadius.all(Radius.circular(12)),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: DateTimePicker(
initialValue: DateTime.now().toString(),
//initialValue:'', // initialValue or controller.text can be null, empty or a DateTime string otherwise it will throw an error.
type: DateTimePickerType.date,
dateLabelText: 'Select Date',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 3.5,
fontFamily: 'Poppins',
color: Colors.green,
letterSpacing: 2.0,
),
firstDate: DateTime.now(),
lastDate: DateTime.now().add(Duration(days: 30)),
// This will add one year from current date
validator: (value) {
return null;
},
onChanged: (value) {
if (value.isNotEmpty) {
setState(() {
_selectedDate = value;
});
}
},
onSaved: (value) {
if (value.isNotEmpty) {
_selectedDate = value;
}
},
),
),
),
ListTile(
title: Text(
"Select Pathological Lab",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 4.0,
fontFamily: 'Poppins',
color: Theme.of(context).primaryColor,
),
),
),
Container(
child: FutureBuilder<List<Partner>>(
future: getAllPathLabResults,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Somthing went wrong");
}
if (snapshot.hasData) {
List<Partner> data =
snapshot.hasData ? snapshot.data : [];
return DropdownButton<Partner>(
value: _selectedLab,
hint: Text("Select Lab"),
//underline: SizedBox(),
//isExpanded: true,
items: data
.map((Partner data) => DropdownMenuItem<Partner>(
child: Text("${data.partnerName}"),
value: data,
))
.toList()
.cast<DropdownMenuItem<Partner>>(),
onChanged: (value) {
setState(() {
_selectedLab = value;
encLabId = value.encPartnerId;
getTestByLabResult = getTestByLab();
});
//GetTestByLab(value!.encPartnerId); // passing encid to my next API function
// GetTestByLab();
},
);
}
return Text("Waiting for Internet Connection");
},
),
),
//=========================================================== Dependent drop down===================================
ListTile(
title: Text(
"Test Name",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: blockSizeHorizontal * 4.0,
fontFamily: 'Poppins',
color: Theme.of(context).primaryColor,
),
),
),
Container(
child: FutureBuilder<List<Datum>>(
future: getTestByLabResult,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text("Select a Lab for your Test");
}
if (snapshot.hasData) {
List<Datum> data = snapshot.hasData ? snapshot.data : [];
return DropdownButton<Datum>(
value: _selectedTest,
hint: Text(""),
//underline: SizedBox(),
//isExpanded: true,
items: data
.map((Datum data) => DropdownMenuItem<Datum>(
child: Text("${data.testName}"),
value: data,
))
.toList()
.cast<DropdownMenuItem<Datum>>(),
onChanged: (value) {
print("This is the value : ${value.testName}");
setState(() {
_selectedTest = value;
});
//GetTestByLab(value!.encPartnerId); // passing encid to my next API function
});
}
return Text("Waiting for Internet Connection");
},
),
),
],
),
),
),
);
}
}
// used this as a sample
String jsonstring = '''{
"Status": "1",
"Message": "",
"Partner": [
{
"EncPartnerId": "IujyQXg8KZg8asLvK/FS7g==",
"PartnerName": "dasfdsf"
},
{
"EncPartnerId": "pEl2B9kuumKRxIxLJO76eQ==",
"PartnerName": "partner172"
},
{
"EncPartnerId": "eYwtNBXR6P/JDtsIwr+Bvw==",
"PartnerName": "nnkb"
},
{
"EncPartnerId": "kFgorcFF0G6RQD4W+LwWnQ==",
"PartnerName": "nnkjj"
},
{
"EncPartnerId": "U4exk+vfMGrn7cjNUa/PBw==",
"PartnerName": "mahadev"
},
{
"EncPartnerId": "tqkaSjTFgDf0612mp9mbsQ==",
"PartnerName": null
},
{
"EncPartnerId": "0aruO0FbYOu5IerRBxdT8w==",
"PartnerName": "Suraksha Diagnostics"
},
{
"EncPartnerId": "65gtodyhbtdInTsJWr1ZkA==",
"PartnerName": "Rasomoy pvt. Hospital"
},
{
"EncPartnerId": "LEuT1eIlpLEMAAkZme3wpQ==",
"PartnerName": "Tangra medical House"
},
{
"EncPartnerId": "q8O8YMzYKXSB4RtkX4k7Lw==",
"PartnerName": "Partner new"
}
]
}''';
Models for the apis:
// To parse this JSON data, do
//
// final model = modelFromJson(jsonString);
import 'dart:convert';
Model modelFromJson(String str) => Model.fromJson(json.decode(str));
String modelToJson(Model data) => json.encode(data.toJson());
class Model {
Model({
this.status,
this.message,
this.partner,
});
String status;
String message;
List<Partner> partner;
factory Model.fromJson(Map<String, dynamic> json) => Model(
status: json["Status"],
message: json["Message"],
partner:
List<Partner>.from(json["Partner"].map((x) => Partner.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Status": status,
"Message": message,
"Partner": List<dynamic>.from(partner.map((x) => x.toJson())),
};
}
class Partner {
Partner({
this.encPartnerId,
this.partnerName,
});
String encPartnerId;
String partnerName;
factory Partner.fromJson(Map<String, dynamic> json) => Partner(
encPartnerId: json["EncPartnerId"],
partnerName: json["PartnerName"] == null ? null : json["PartnerName"],
);
Map<String, dynamic> toJson() => {
"EncPartnerId": encPartnerId,
"PartnerName": partnerName == null ? null : partnerName,
};
}
second api parsing model
// To parse this JSON data, do
//
// final dataModel = dataModelFromJson(jsonString);
import 'dart:convert';
DataModel dataModelFromJson(String str) => DataModel.fromJson(json.decode(str));
String dataModelToJson(DataModel data) => json.encode(data.toJson());
class DataModel {
DataModel({
this.status,
this.message,
this.data,
});
String status;
String message;
List<Datum> data;
factory DataModel.fromJson(Map<String, dynamic> json) => DataModel(
status: json["Status"],
message: json["Message"],
data: json["Data"] == null
? []
: List<Datum>.from(json["Data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Status": status,
"Message": message,
"Data":
data == null ? [] : List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.testId,
this.encTestId,
this.testName,
this.noOfPartner,
this.testFee,
this.discountedFee,
this.bookingFee,
this.reportTime,
this.note,
this.createBy,
this.createDate,
this.modBy,
this.modDate,
this.activeStatus,
this.permission,
});
String testId;
dynamic encTestId;
String testName;
dynamic noOfPartner;
dynamic testFee;
dynamic discountedFee;
dynamic bookingFee;
dynamic reportTime;
dynamic note;
dynamic createBy;
dynamic createDate;
dynamic modBy;
dynamic modDate;
dynamic activeStatus;
dynamic permission;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
testId: json["TestId"],
encTestId: json["EncTestId"],
testName: json["TestName"],
noOfPartner: json["NoOfPartner"],
testFee: json["TestFee"],
discountedFee: json["DiscountedFee"],
bookingFee: json["BookingFee"],
reportTime: json["ReportTime"],
note: json["Note"],
createBy: json["CreateBy"],
createDate: json["CreateDate"],
modBy: json["ModBy"],
modDate: json["ModDate"],
activeStatus: json["ActiveStatus"],
permission: json["Permission"],
);
Map<String, dynamic> toJson() => {
"TestId": testId,
"EncTestId": encTestId,
"TestName": testName,
"NoOfPartner": noOfPartner,
"TestFee": testFee,
"DiscountedFee": discountedFee,
"BookingFee": bookingFee,
"ReportTime": reportTime,
"Note": note,
"CreateBy": createBy,
"CreateDate": createDate,
"ModBy": modBy,
"ModDate": modDate,
"ActiveStatus": activeStatus,
"Permission": permission,
};
}
So when you initially fetch the data based on the id and select the second dropdown. now when you change the lab you have the make the selected text to null.
and you are are also using the futurebuilder method in wrong manner as there is setstate getting called it is creating multiple rebuids and giving error.
please run the code and check if its working.

returning a widget based on the json result from POST method in flutter

my dashboard.dart look like this
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:abc/utils/connection_config.dart';
import 'package:abc/screens/loginpage.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/cupertino.dart';
class Dash extends StatefulWidget {
#override
DashState createState() => DashState();
}
class DashState extends State<Dash> {
Future reportList;
#override
void initState() {
super.initState();
reportList = getDashboardData();
}
getDashboardData() async {
var fromtime = 1567449000000;
var totime = 1567770486144;
var mtype = "internet";
http.Response response = await http.post(dashboardURL,
headers: {"Content-type": "application/json"},
body: json.encode({
"fromTime": fromtime,
"mtype": mtype,
"must": [
{"msg_status": "0"}
],
"toTime": totime
}));
switch (response.statusCode) {
case 200:
String dashboardResult = response.body;
var collection = json.decode(dashboardResult);
return collection;
break;
case 403:
case 401:
return null;
default:
return 1;
}
}
Widget getContents(BuildContext context, var data) { //here I want to return the widget for each entry in hits array
Widget _widget;
_widget = SingleChildScrollView(
child: SingleChildScrollView(
child: Container(
child: ,
),
),
);
return _widget;
}
//function that iterates over the list
getRefreshScaffold() {
return Center(
child: RaisedButton(
onPressed: () {
setState(() {
reportList = getDashboardData();
});
},
child: Text('Refresh, Network issues.'),
),
);
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: reportList,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.active:
return Center(
child: CircularProgressIndicator(),
);
case ConnectionState.done:
var data = snapshot.data;
if (snapshot.hasData && !snapshot.hasError) {
return Container(
child: getContents(context, snapshot.data),
);
} else if (data == null) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Timeout! Log back in to continue"),
Padding(
padding: EdgeInsets.all(25.0),
),
RaisedButton(
onPressed: () {
setState(() {
token = null;
});
Navigator.of(context).pushReplacement(
CupertinoPageRoute(
builder: (BuildContext context) => LoginPage()),
);
},
child: Text('Login Again!'),
),
],
),
);
} else {
getRefreshScaffold();
}
}
},
);
}
}
Here I am hitting an api that gives the json there i need to loop over the following ,
{
..... some other data
"hitsArray": [
{
"tt": 1567566438144,
"status": "0",
"count": 2257056,
"status_count": 2257053
},
{
"tt": 1567566438144,
"status": "1",
"count": 2257056,
"status_count": 3
}
],
...some other data
}
what iam trying to do is to loop over the hitsarray in the json result and to display each entry in a widget.
but i am not getting how to loop over the json data and assign an widget to display it, I tried my best but not able to get it.
paste your json string to https://app.quicktype.io/ and you can get correct parsing logic and you can display with ListView
you can modify delay during to simulate network delay.
await new Future.delayed(new Duration(seconds: 10));
if your json string look like this
[
{
"tt": 1567566438144,
"status": "0",
"count": 2257056,
"status_count": 2257053
}
,
{
"tt": 1567566438144,
"status": "1",
"count": 2257056,
"status_count": 3
}
]
logic from quicktype
// To parse this JSON data, do
//
// final hitsArray = hitsArrayFromJson(jsonString);
import 'dart:convert';
List<HitsArray> hitsArrayFromJson(String str) => List<HitsArray>.from(json.decode(str).map((x) => HitsArray.fromJson(x)));
String hitsArrayToJson(List<HitsArray> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class HitsArray {
int tt;
String status;
int count;
int statusCount;
HitsArray({
this.tt,
this.status,
this.count,
this.statusCount,
});
factory HitsArray.fromJson(Map<String, dynamic> json) => HitsArray(
tt: json["tt"],
status: json["status"],
count: json["count"],
statusCount: json["status_count"],
);
Map<String, dynamic> toJson() => {
"tt": tt,
"status": status,
"count": count,
"status_count": statusCount,
};
}
demo full code display with FutureBuilder and ListView
import 'dart:async';
import 'package:flutter/material.dart';
// To parse this JSON data, do
//
// final hitsArray = hitsArrayFromJson(jsonString);
import 'dart:convert';
List<HitsArray> hitsArrayFromJson(String str) => List<HitsArray>.from(json.decode(str).map((x) => HitsArray.fromJson(x)));
String hitsArrayToJson(List<HitsArray> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class HitsArray {
int tt;
String status;
int count;
int statusCount;
HitsArray({
this.tt,
this.status,
this.count,
this.statusCount,
});
factory HitsArray.fromJson(Map<String, dynamic> json) => HitsArray(
tt: json["tt"],
status: json["status"],
count: json["count"],
statusCount: json["status_count"],
);
Map<String, dynamic> toJson() => {
"tt": tt,
"status": status,
"count": count,
"status_count": statusCount,
};
}
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
var futureBuilder = new FutureBuilder(
future: _getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return new Text('loading...');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return createListView(context, snapshot);
}
},
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Home Page"),
),
body: futureBuilder,
);
}
Future<List<HitsArray>> _getData() async {
String jsonString = ' [ { "tt": 1567566438144, "status": "0", "count": 2257056, "status_count": 2257053 } , { "tt": 1567566438144, "status": "1", "count": 2257056, "status_count": 3 } ]';
var values = hitsArrayFromJson(jsonString);
//throw new Exception("Danger Will Robinson!!!");
await new Future.delayed(new Duration(seconds: 1));
return values;
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
List<HitsArray> values = snapshot.data;
return new ListView.builder(
itemCount: values.length,
itemBuilder: (BuildContext context, int index) {
return new Column(
children: <Widget>[
new ListTile(
title: new Text(' count ${values[index].count.toString()}'),
subtitle: new Text('status count ${values[index].statusCount.toString()}'),
),
new Divider(height: 2.0,),
],
);
},
);
}
}