How to create souce for Paginateddatatable using FromJson model? - json

I am using Mysql database as backend for flutter Web App.
I have created api and model to fetch data from mysql. I am able to get the table data as Json formate. I am able to ftech the json data getting from Browser.
I want to fetch this data in to paginatedDataTable on flutter web app. I am facing issue that how to ftech this data in to paginatedDataTable. PLease help me how to do this.
How to fetch json data in to paginatedDataTable on flutter web app.
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("http://localhost:3000/employees_router/all");
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 incomplete example Code with paginatedDataTable:
import 'package:flutter/material.dart';
import 'package:webappmysql/employees_model.dart';
import 'package:webappmysql/employees_api.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Container(
padding: const EdgeInsets.all(16.0),
child: FutureBuilder(
future: fetchEmployees(),
builder: (BuildContext ctx, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
//shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
Employees employee = snapshot.data[index];
////return Text(user.title);
return PaginatedDataTable(
source: _dataSource,
header: const Text('Employees'),
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Email')),
],
columnSpacing: 100,
horizontalMargin: 10,
rowsPerPage: 8,
showCheckboxColumn: false,
);
// return ListTile(
// title: Text(employee.id.toString()),
// subtitle: Text(employee.name),
// contentPadding: const EdgeInsets.only(bottom: 20.0),
// );
},
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
);
}
}

change your HomePage to this.
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: FutureBuilder(
future: fetchEmployees(),
builder: (BuildContext ctx, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: PaginatedDataTable(
source: dataSource(snapshot.data),
header: const Text('Employees'),
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Email')),
],
showCheckboxColumn: false,
),
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
);
}
DataTableSource dataSource(List<Employees> employeesList) =>
MyData(dataList: employeesList);
}
class MyData extends DataTableSource {
MyData({required this.dataList});
final List<Employees> dataList;
// Generate some made-up data
#override
bool get isRowCountApproximate => false;
#override
int get rowCount => dataList.length;
#override
int get selectedRowCount => 0;
#override
DataRow getRow(int index) {
return DataRow(
cells: [
DataCell(
Text(dataList[index].id.toString()),
),
DataCell(
Text(dataList[index].name),
),
DataCell(
Text(dataList[index].email),
),
],
);
}
}

Related

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(),
);
},
),
],
),
),
);
}}

Create list throws List<dynamic> is not subtype of type Map<string, dynamic>

I'm try ti create a list from a json but it throws me the error: "List is not subtype of type Map<string, dynamic>".
The first part of code is where I am trying to create the list bwhich is in a widget that is called to the main widget.On the second block of code is where I do the fetch and recives an endpoint and then returns the response back and the last one is the structure of the json.
import 'package:flutter/material.dart';
import 'package:eshop/models/products.dart';
import 'package:eshop/function/fetch.dart';
const endPoint = 'https://sistemas.cruzperez.com/flutter/jsonPrueba.json';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future<Product> futureProduct;
#override
void initState() {
super.initState();
futureProduct = getData(endPoint);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
title: Text('Eshop'),
automaticallyImplyLeading: false,
actions: <Widget>[
IconButton(icon: Icon(Icons.shopping_cart, color: Colors.white), onPressed: (){})
],
),
body: Center(
child: Container(
child: Column(
children: <Widget>[
listJson(futureProduct)
],
),
)
),
);
}
}
Widget listJson(futureProduct){
return Container(
child: FutureBuilder<Product>(
future: futureProduct,
builder: (context, snapshot){
if(snapshot.hasData){
return Text(snapshot.data.nombre);
}else if(snapshot.hasError){
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
);
}
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:eshop/models/products.dart';
Future<Product> getData(endPoint) async{
final response = await http.get(endPoint);
if (response.statusCode == 200) {
return Product.fromJson(json.decode(response.body));
}else{
throw Exception('Error a cargar json');
}
}
class Product{
final int idSucursal;
final int idProducto;
final String nombre;
final String categoria;
final int precio;
final int disponible;
final String descripcion;
final String imgUrl;
Product({
this.idSucursal,
this.idProducto,
this.nombre,
this.categoria,
this.precio,
this.disponible,
this.descripcion,
this.imgUrl
});
factory Product.fromJson(Map<String, dynamic> json){
return Product(
idSucursal: json['id_sucursal'],
idProducto: json['id_producto'],
nombre: json['nombre'],
categoria: json['categoria'],
precio: json['precio'],
disponible: json['disponible'],
descripcion: json['descripcion'],
imgUrl: json['img_url'],
);
}
}
You can copy paste run full code below
Step 1: You need to use List<Product> and parse with productFromJson
List<Product> productFromJson(String str) =>
List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
Step 2: You can display data with ListView
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Card(
elevation: 6.0,
child: Padding(
padding: const EdgeInsets.only(
top: 6.0, bottom: 6.0, left: 8.0, right: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(snapshot.data[index].nombre.toString()),
],
),
));
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
List<Product> productFromJson(String str) =>
List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
String productToJson(List<Product> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Product {
Product({
this.idSucrsal,
this.idProducto,
this.nombre,
this.categoria,
this.precio,
this.disponible,
this.descripcion,
this.imgUrl,
});
int idSucrsal;
int idProducto;
String nombre;
Categoria categoria;
int precio;
int disponible;
String descripcion;
String imgUrl;
factory Product.fromJson(Map<String, dynamic> json) => Product(
idSucrsal: json["id_sucrsal"],
idProducto: json["id_producto"],
nombre: json["nombre"],
categoria: categoriaValues.map[json["categoria"]],
precio: json["precio"],
disponible: json["disponible"],
descripcion: json["descripcion"],
imgUrl: json["img_url"],
);
Map<String, dynamic> toJson() => {
"id_sucrsal": idSucrsal,
"id_producto": idProducto,
"nombre": nombre,
"categoria": categoriaValues.reverse[categoria],
"precio": precio,
"disponible": disponible,
"descripcion": descripcion,
"img_url": imgUrl,
};
}
enum Categoria { RES, CERDO, EMBUTIDO }
final categoriaValues = EnumValues({
"cerdo": Categoria.CERDO,
"embutido": Categoria.EMBUTIDO,
"res": Categoria.RES
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
const endPoint = 'https://sistemas.cruzperez.com/flutter/jsonPrueba.json';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future<List<Product>> futureProduct;
Future<List<Product>> getData(endPoint) async {
final response = await http.get(endPoint);
if (response.statusCode == 200) {
return productFromJson(response.body);
} else {
throw Exception('Error a cargar json');
}
}
#override
void initState() {
super.initState();
futureProduct = getData(endPoint);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Eshop'),
automaticallyImplyLeading: false,
actions: <Widget>[
IconButton(
icon: Icon(Icons.shopping_cart, color: Colors.white),
onPressed: () {})
],
),
body: Center(
child: Container(
child: Column(
children: <Widget>[Expanded(child: listJson(futureProduct))],
),
)),
);
}
}
Widget listJson(futureProduct) {
return Container(
child: FutureBuilder<List<Product>>(
future: futureProduct,
builder: (context, AsyncSnapshot<List<Product>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Card(
elevation: 6.0,
child: Padding(
padding: const EdgeInsets.only(
top: 6.0, bottom: 6.0, left: 8.0, right: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(snapshot.data[index].nombre.toString()),
],
),
));
});
}
}
},
),
);
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}

Flutter: JSON data , list under list

I have JSON data file that looks like this, as you can see the email is a list itself:
[
{
"index": 0,
"about": "text text text",
"email": [
"kjdkffsk#skfjsd.com",
"kjdkffsk#skfjsd.com",
],
"name": "sample name",
"picture": "https://kdjfksfjsdklfs.com"
},
{
"index": 1,
"about": "text text text",
"email": [
"kjdkffsk#skfjsd.com",
"kjdkffsk#skfjsd.com",
],
"name": "sample name ",
"picture": "https://kdjfksfjsdklfs.com"
},
{
"index": 2,
"about": "text text text",
"email": [
"kjdkffsk#skfjsd.com",
"kjdkffsk#skfjsd.com",
],
"name": "sample name",
"picture": "https://kdjfksfjsdklfs.com"
}
]
My code is the following, which is basically a listview builder that gets data from the above JSON. Now when the list is clicked it navigate to the next page where I need to show details of this user.
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
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(title: 'Users'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
Future _data;
class _MyHomePageState extends State<MyHomePage> {
Future<List<User>> _getUsers() async {
var data =
await DefaultAssetBundle.of(context).loadString("assets/test.json");
var jsonData = json.decode(data);
List<User> users = [];
for (var u in jsonData) {
User user =
User(u["index"], u["about"], u["name"], u["email"], u["picture"]);
users.add(user);
}
print(users.length);
return users;
}
#override
void initState() {
super.initState();
_data = _getUsers();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
child: FutureBuilder(
future: _data,
builder: (BuildContext context, AsyncSnapshot snapshot) {
print(snapshot.data);
if (snapshot.data == null) {
return Container(child: Center(child: Text("Loading...")));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundImage:
NetworkImage(snapshot.data[index].picture),
),
title: Text(snapshot.data[index].name),
// subtitle: Text(snapshot.data[index].email),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailPage(snapshot.data[index])));
},
);
},
);
}
},
),
),
);
}
}
class DetailPage extends StatelessWidget {
final User user;
DetailPage(this.user);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(user.name),
),
body: Container(
child: Text(user.about),
),
);
}
}
class User {
final int index;
final String about;
final String name;
final String email;
final String picture;
User(this.index, this.about, this.name, this.email, this.picture);
}
I wanted to create Listview Builder in the second page for name and the email so that all the emails listed under the name.
can someone help I am not able to generate the second page list especially the email list.
Just check out this example and let me know if it works for you:
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:json_parsing_example/models.dart';
// To parse this JSON data, do
//
// final user = userFromJson(jsonString);
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(title: 'Users'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
Future _data;
class _MyHomePageState extends State<MyHomePage> {
Future<List<User>> _getUsers() async {
var data =
await DefaultAssetBundle.of(context).loadString("json/parse.json");
return userFromJson(data);
}
#override
void initState() {
super.initState();
_data = _getUsers();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
child: FutureBuilder<List<User>>(
future: _data,
builder: (BuildContext context, AsyncSnapshot snapshot) {
print(snapshot.data);
if (snapshot.data == null) {
return Container(child: Center(child: Text("Loading...")));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundImage:
NetworkImage(snapshot.data[index].picture),
),
title: Text(snapshot.data[index].name),
// subtitle: Text(snapshot.data[index].email),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailPage(snapshot.data[index])));
},
);
},
);
}
},
),
),
);
}
}
class DetailPage extends StatefulWidget {
final User user;
DetailPage(this.user);
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.user.name),
),
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
widget.user.name,
style: TextStyle(fontSize: 20),
),
),
ListView.builder(
shrinkWrap: true,
itemCount: widget.user.email.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(widget.user.email[index]),
));
},
),
],
),
),
);
}
}
Your model class :
// To parse this JSON data, do
//
// final user = userFromJson(jsonString);
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 {
User({
this.index,
this.about,
this.email,
this.name,
this.picture,
});
int index;
String about;
List<String> email;
String name;
String picture;
factory User.fromJson(Map<String, dynamic> json) => User(
index: json["index"],
about: json["about"],
email: List<String>.from(json["email"].map((x) => x)),
name: json["name"],
picture: json["picture"],
);
Map<String, dynamic> toJson() => {
"index": index,
"about": about,
"email": List<dynamic>.from(email.map((x) => x)),
"name": name,
"picture": picture,
};
}
First of all:
You can use either
moor/moor_flutter moor flutter_moor
OR
built_value built_value
To map the json String and generate fromJson/toJson functions.
Example using moor:
First, create a moor database (if you have any question I am glad to answer).
Second, this would be the class you should use.
import 'dart:convert';
import 'package:db/moordb/database.dart';
import 'package:json_annotation/json_annotation.dart' as json;
import 'package:moor/moor.dart';
part 'user.g.dart';
#DataClassName("User")
class Users extends Table {
IntColumn get id => integer().nullable().autoIncrement()();
#JsonKey("index")
IntColumn get index => text().nullable()();
#JsonKey("about")
TextColumn get about => text().nullable()();
#JsonKey("email")
TextColumn get emails => text().map(const EmailConverter()).nullable()();
#JsonKey("name")
TextColumn get name => text().nullable()();
#JsonKey("picture")
TextColumn get picture => text().nullable()();
#override
Set<Column> get primaryKey => {id};
}
class EmailConverter extends TypeConverter<List<String>, String> {
const EmailConverter ();
#override
List<String> mapToDart(String fromDb) {
if (fromDb == null) {
return null;
}
List _emails = List<String>();
(jsonDecode(fromDb)).forEach((value) {
_emails.add(value);
});
return _emails;
}
#override
String mapToSql(List<dynamic> value) {
if (value == null) {
return null;
}
return jsonEncode(value);
}
}
Second:
It is preferred that you send the User object through:
Navigator arguments Navigation
or
An Inherited Widget Inherited Widget
In your case you are passing the object to the widget directly.
In conclusion, it is obvious that the String field email in your User object is not being populated by the decoded data which contains the emails in a List. (since you are using the Class User).
Note: lose the new keyword since it is no longer required in Dart 2

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,),
],
);
},
);
}
}