JSON data coming from API not showing in the dropdownlist - flutter

I am using JSON API to get the data into my dropdownlist in Flutter. But whenever I am clicking on the dropdownlist the data does not appear in the list.
Following is my code:
class ItemSelection extends StatefulWidget{
#override
_ItemSelectionState createState() => _ItemSelectionState();
}
class _ItemSelectionState extends State<ItemSelection> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("Dropdown",
style: TextStyle(
fontSize: 20.0,
),
textAlign: TextAlign.center,
),
SizedBox(
height: 20.0,
),
DropDownField(
controller: cityselected,
hintText: "Select an item",
enabled: true,
itemsVisibleInDropdown: 5,
items: items,
onValueChanged: (value){
setState(() {
selectedcity = value;
});
}
)
],
),
),
);
}
}
final List<String> items = [];
Future getitem() async {
var response = await http.get(
"basic json url here",
headers: {
"Accept": "application/json"
}
);
if(response.statusCode == 200){
List<GetItem> getitem = getItemFromJson(response.body);
for(int i =0; i< getitem.length; i++){
items.add(getitem[i].itemName);
}
print(items);
}
}
GetItem.dart:
import 'dart:convert';
List<GetItem> getItemFromJson(String str) => List<GetItem>.from(json.decode(str).map((x) => GetItem.fromJson(x)));
String getItemToJson(List<GetItem> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class GetItem {
GetItem({
this.sLNo,
this.itemName,
this.category,
});
String sLNo;
String itemName;
String category;
factory GetItem.fromJson(Map<String, dynamic> json) => GetItem(
sLNo: json["S/L NO"],
itemName: json["Item Name"] == null ? null : json["Item Name"],
category: json["Category"] == null ? null : json["Category"],
);
Map<String, dynamic> toJson() => {
"S/L NO": sLNo,
"Item Name": itemName == null ? null : itemName,
"Category": category == null ? null : category,
};
}
As soon as I click on the dropdownlist I want the data coming from the JSON API to show in there. Can someone help me with this please?

You can copy paste run full code below
You can use FutureBuilder
code snippet
Future<List<String>> _future;
#override
void initState() {
_future = getitem();
...
FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot<List<String>> 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 DropDownField(
controller: cityselected,
hintText: "Select an item",
enabled: true,
itemsVisibleInDropdown: 5,
items: snapshot.data,
onValueChanged: (dynamic value) {
setState(() {
selectedcity = value;
});
});
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:dropdownfield/dropdownfield.dart';
import 'package:http/http.dart' as http;
List<GetItem> getItemFromJson(String str) =>
List<GetItem>.from(json.decode(str).map((x) => GetItem.fromJson(x)));
String getItemToJson(List<GetItem> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class GetItem {
GetItem({
this.sLNo,
this.itemName,
this.category,
});
String sLNo;
String itemName;
String category;
factory GetItem.fromJson(Map<String, dynamic> json) => GetItem(
sLNo: json["S/L NO"],
itemName: json["Item Name"] == null ? null : json["Item Name"],
category: json["Category"] == null ? null : json["Category"],
);
Map<String, dynamic> toJson() => {
"S/L NO": sLNo,
"Item Name": itemName == null ? null : itemName,
"Category": category == null ? null : category,
};
}
class ItemSelection extends StatefulWidget {
#override
_ItemSelectionState createState() => _ItemSelectionState();
}
class _ItemSelectionState extends State<ItemSelection> {
TextEditingController cityselected = TextEditingController();
String selectedcity;
Future<List<String>> _future;
#override
void initState() {
_future = getitem();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"Dropdown",
style: TextStyle(
fontSize: 20.0,
),
textAlign: TextAlign.center,
),
SizedBox(
height: 20.0,
),
FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot<List<String>> 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 DropDownField(
controller: cityselected,
hintText: "Select an item",
enabled: true,
itemsVisibleInDropdown: 5,
items: snapshot.data,
onValueChanged: (dynamic value) {
setState(() {
selectedcity = value;
});
});
}
}
})
],
),
),
);
}
}
final List<String> items = [];
Future<List<String>> getitem() async {
/*var response = await http
.get("basic json url here", headers: {"Accept": "application/json"});*/
String jsonString = '''
[{
"S/L NO":"1",
"Item Name":"item 1",
"Category": "c1"
},
{
"S/L NO":"2",
"Item Name":"item 2",
"Category": "c2"
},
{
"S/L NO":"3",
"Item Name":"item 3",
"Category": "c3"
},
{
"S/L NO":"4",
"Item Name":"item 4",
"Category": "c4"
},
{
"S/L NO":"5",
"Item Name":"item 5",
"Category": "c5"
}
]
''';
http.Response response = http.Response(jsonString, 200);
if (response.statusCode == 200) {
List<GetItem> getitem = getItemFromJson(response.body);
print(getitem.length);
for (int i = 0; i < getitem.length; i++) {
items.add(getitem[i].itemName);
}
}
return items;
}
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: ItemSelection(),
);
}
}

setState(() {
for(int i =0; i< getitem.length; i++){
items.add(getitem[i].itemName);
}
});

Related

How to fetch data API to dropdown

how do I call the API data into the dropdown I have done several times, when I used local data in the form of a String list I managed to call the data, but when I tried to call from the API data the result was empty and the results in the dropdown did not display any data
Future<List<Agama>> getAgama() async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
final response = await http.get(
Uri.parse(
'$url/auth/mhs_siakad/dosen',
),
headers: {
'Authorization': 'Bearer $token',
},
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
final result =
json.decode(response.body)['nm_agama'] as Map<String, dynamic>;
UserBiodata agama = UserBiodata.fromJson(result);
List<Agama> l = agama.data ?? [];
return l;
} else {
throw Exception();
}
}
in widget
List<Agama>? religion = [];
#override
void initState() {
super.initState();
BiodataProvider().getAgama();
}
var dropdownAgama;
...
FutureBuilder(
future: BiodataProvider().getBiodata(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(' ini Agama $religion');
return Column(
children: [
Text(
snapshot.data!.data!.name.toString(),
style: bold5,
),
DropdownButton(
hint: const Text('Religion'),
items: religion!.map((item) {
return DropdownMenuItem(
value: item.nmAgama.toString(),
child: Text(item.idAgama.toString()),
);
}).toList(),
onChanged: (newVal) {
setState(() {
dropdownAgama = newVal;
});
},
value: dropdownAgama,
),
],
);
} else {
return const Text('No Data');
}
}),
...
this is the model i am using which is converted from API
class Agama {
String? id;
String? idAgama;
String? nmAgama;
String? createdAt;
String? updatedAt;
dynamic createdBy;
dynamic updatedBy;
Agama(
{this.id,
this.idAgama,
this.nmAgama,
this.createdAt,
this.updatedAt,
this.createdBy,
this.updatedBy});
Agama.fromJson(Map<String, dynamic> json) {
id = json['id'];
idAgama = json['id_agama'];
nmAgama = json['nm_agama'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
createdBy = json['created_by'];
updatedBy = json['updated_by'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['id_agama'] = idAgama;
data['nm_agama'] = nmAgama;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
data['created_by'] = createdBy;
data['updated_by'] = updatedBy;
return data;
}
}
it looks like you are not assigning your api data to the
List<Agama>? religion;
you can solve this by either mapping your snapshot data directly:
#override
void initState() {
super.initState();
BiodataProvider().getAgama();
}
var dropdownAgama;
...
FutureBuilder(
future: BiodataProvider().getBiodata(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(' ini Agama $religion');
return Column(
children: [
Text(
snapshot.data!.data!.name.toString(),
style: bold5,
),
DropdownButton(
hint: const Text('Religion'),
items: snapshot.data!.data!.map((item) {
return DropdownMenuItem(
value: item.nmAgama.toString(),
child: Text(item.idAgama.toString()),
);
}).toList(),
onChanged: (newVal) {
setState(() {
dropdownAgama = newVal;
});
},
value: dropdownAgama,
),
],
);
} else {
return const Text('No Data');
}
}),
or
by assigning the snapshot data to your list:
List<Agama>? religion = [];
#override
void initState() {
super.initState();
BiodataProvider().getAgama();
}
var dropdownAgama;
...
FutureBuilder(
future: BiodataProvider().getBiodata(),
builder: (context, snapshot) {
if (snapshot.hasData) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState((){
religion = snapshot.data!.data;
})
});
print(' ini Agama $religion');
return Column(
children: [
Text(
snapshot.data!.data!.name.toString(),
style: bold5,
),
DropdownButton(
hint: const Text('Religion'),
items: religion!.map((item) {
return DropdownMenuItem(
value: item.nmAgama.toString(),
child: Text(item.idAgama.toString()),
);
}).toList(),
onChanged: (newVal) {
setState(() {
dropdownAgama = newVal;
});
},
value: dropdownAgama,
),
],
);
} else {
return const Text('No Data');
}
}),
hope this helps!
Solution
In Controller Class,
Initialize your Future Method as your Model : Future<List<LeaveModel>> getLeaves(){}
create a List of Obj for Custom Class like this :
List<LeaveModel> leaveTypeObjList = [];
After fetching data from API add the datas in obj list via Object
type :LeaveModel leaveTypeObj = LeaveModel(leaveTypeResponseList[i]["LEAVE_TYPE_EN"]);
And in loop add it to your obj list: leaveTypeObjList.add(leaveTypeObj);
** In widget class at AsyncSnapshot use your List of Generics like this :
AsyncSnapshot<List<LeaveModel>>.
Demo Code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main(List<String> args) {
runApp(MyHome());
}
class MyHome extends StatelessWidget {
const MyHome({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyApp(),
);
}
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<String> leaveTypeList = [];
int currentLeaveType = 0;
String? value;
String? selectedLeaveType;
late Future<List<LeaveModel>> futureLeaves;
#override
void initState() {
super.initState();
futureLeaves = FoodTypeController().getLeaves();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: double.infinity,
width: double.infinity,
child: Row(
children: [
Text(
"Leave Type = ",
style: TextStyle(fontSize: 24.0),
),
FutureBuilder(
future: futureLeaves,
builder: ((BuildContext context,
AsyncSnapshot<List<LeaveModel>> snapshot) {
if (snapshot.hasData) {
leaveTypeList = [];
List<LeaveModel>? LeaveTypes = snapshot.data;
for (int i = 0; i < LeaveTypes!.length; i++) {
leaveTypeList.add(LeaveTypes[i].leaveTypes!);
}
return SizedBox(
width: 200,
height: 50,
child: Container(
padding: EdgeInsets.only(left: 2.0, right: 4.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.black, width: 1)),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
borderRadius: BorderRadius.circular(12),
value: currentLeaveType == null? null: leaveTypeList[currentLeaveType],
icon: Icon(Icons.arrow_drop_down_rounded),
items: leaveTypeList.map(buildMenuItem).toList(),
onChanged: (value) => setState(() {
currentLeaveType = leaveTypeList.indexOf(value.toString());
this.value = value;
selectedLeaveType = this.value;
}),
),
),
),
);
} else if (snapshot.hasError) {
return const Text("Error to load Snapshot");
} else {
return const CircularProgressIndicator();
}
})),
],
),
),
);
}
DropdownMenuItem<String> buildMenuItem(String item) => DropdownMenuItem(
value: item,
child: Text(
item.toString(),
style: TextStyle(fontWeight: FontWeight.w400, fontSize: 24.0),
),
);
}
class LeaveModel {
String? leaveTypes;
LeaveModel(this.leaveTypes);
}
class FoodTypeController {
Future<List<LeaveModel>> getLeaves() async {
List<LeaveModel> leaveTypeObjList = [];
String url = "";
http.Response response =
await http.post(Uri.parse(url), body: {"user": "", "pass": ""});
if (response.statusCode == 200) {
List leaveTypeResponseList = jsonDecode(response.body);
for (int i = 0; i < leaveTypeResponseList.length; i++) {
LeaveModel leaveTypeObj =
LeaveModel(leaveTypeResponseList[i]["LEAVE_TYPE"]);
leaveTypeObjList.add(leaveTypeObj);
}
return leaveTypeObjList;
} else {
throw Exception("Error to load data in Leave Controller");
}
}
}
Response
Visual

flutter futurebuilder asyncsnapshot to fetch data that is not list

Below is the list of data that i am fetching
[
{
"name": "kamchatka11111",
"email": "kamchatka#mail.com",
"index": 1,
"picture": "https://static.themoscowtimes.com/image/1360/73/TASS40183186.jpg",
"imageFetchType": "networkImage"
},
{
"name": "Valjakutse",
"email": "valjakutse#mail.com",
"index": 2,
"picture": "https://images.unsplash.com/photo-1561406636-b80293969660?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8YmxhY2slMjBsYWR5fGVufDB8fDB8fA%3D%3D&w=1000&q=80",
"imageFetchType": "imageNetwork"
},
{
"name": "einstein",
"email": "einstein#mail.com",
"index": 12,
"picture": "https://static.dw.com/image/45897958_303.jpg",
"imageFetchType": "fadeInImage"
}
]
Below is how i am populating this list in my flutter class
import 'package:flutter/material.dart';
import 'package:master_learn/classes/async_futures.dart';
import 'package:master_learn/classes/config.dart';
import 'package:master_learn/lists_grids_screens/user_details.dart';
import 'package:master_learn/widgets/marquee_widget.dart';
class FutureBuilderListUsingHashMap extends StatefulWidget {
const FutureBuilderListUsingHashMap({Key? key}) : super(key: key);
#override
_FutureBuilderListUsingHashMapState createState() =>
_FutureBuilderListUsingHashMapState();
}
class _FutureBuilderListUsingHashMapState
extends State<FutureBuilderListUsingHashMap> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(
Icons.arrow_back,
color: Colors.white,
)),
title: const SizedBox(
child: MarqueeWidget(
direction: Axis.horizontal,
child: Text(
"Fetch"),
),
),
),
body: SizedBox(
child: FutureBuilder(
future: AsyncFutures.fetchListsOfStringDynamicHashMap(),
builder: (BuildContext context, AsyncSnapshot asyncSnapshot) {
if (asyncSnapshot.data == null) {
return const Center(child: CircularProgressIndicator());
} else {
return ListView.builder(
itemCount: asyncSnapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: const EdgeInsets.all(10),
leading: CircleAvatar(
backgroundImage: NetworkImage(
asyncSnapshot.data[index]["picture"] ??
""),
),
title:
Text(asyncSnapshot.data[index]["name"] ?? ''),
subtitle: Text(
"Email: ${asyncSnapshot.data[index]["email"] ?? ''}"),
);
},
);
}
}),
),
);
}
}
The problem i am having is how can i use AsyncSnapshot with FutureBuilder to populate data that is not of a list for example the data below
{
"name": "einstein",
"email": "einstein#mail.com",
"index": 12,
"picture": "https://static.dw.com/image/45897958_303.jpg",
"imageFetchType": "fadeInImage"
}
This may be for example when i am fetching the information for a single profile instead of a list of information of all the profiles
Use the FutureBuilder instead of ListView.builder to fetch a single object. Refer to this awesome explanation in the flutter docs:
https://docs.flutter.dev/cookbook/networking/fetch-data#1-add-the-http-package
To encode your json data into proper flutter object you can visit this website
https://app.quicktype.io/
Hi Emmanuel hope you are well
A recommended practice would be to map your class, converting it from JSON to a class.
Profile class:
class Profile{
final String name;
final String image;
Profile({
#required this.name,
#required this.image,
});
factory Profile.fromJson(Map<String, dynamic> json) {
return Profile(
name: json['name'] as String,
image: json['image'] as String,
);
}
}
Your data request class
class HttpService {
final String profilesURL = "https://sourceDataUrl.example";
Future<List<Profile>> getProfiles() async {
Response res = await get(profilesURL);
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Profile> profiles = body
.map(
(dynamic item) => Profile.fromJson(item),
)
.toList();
return profiles;
} else {
throw "Unable to retrieve profiles.";
}
}
}
and get the request data in a FutureBuilder
class ProfilesPage extends StatelessWidget {
final HttpService httpService = HttpService();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Profile"),
),
body: FutureBuilder(
future: httpService.getProfiles(),
builder: (BuildContext context, AsyncSnapshot<List<Profile>> snapshot) {
if (snapshot.hasData) {
List<Profile> listProfile = snapshot.data;
return ListView(
children: listProfile
.map(
(Profile profile) => ListTile(
name: Text(profile.name),
),
)
.toList(),
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
}
You can refer to this link for more information about http requests.

Duplicate GlobalKey detected in tree widget scaffoldState

I was trying to update data (add, edit, delete) from my list using API, when I clicked something to update the list e.g deleting an item it showed a successfully updated. but in the Debug Console, there's an error that says
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in the widget tree. The following GlobalKey
was specified multiple times in the widget tree. This will lead to
parts of the widget tree being truncated unexpectedly, because the
second time a key is seen, the previous instance is moved to the new
location. The key was:
[LabeledGlobalKey #47c37] This was determined by noticing that after the widget with the above global key was moved out
of its previous parent, that previous parent never updated during this
frame, meaning that it either did not update at all or updated before
the widget was moved, in either case implying that it still thinks
that it should have a child with that global key.
And when I tried going back to the Previous screen it just showed Blank Screen
Here's the code
Model
import 'dart:convert';
class Nasabah {
int id;
String nama_debitur;
String alamat;
String no_telp;
String no_ktp;
String no_selular;
Nasabah({
this.id = 0,
this.nama_debitur,
this.alamat,
this.no_telp,
this.no_ktp,
this.no_selular,
});
factory Nasabah.fromJson(Map<String, dynamic> json) => Nasabah(
id: json["id"],
nama_debitur: json["nama_debitur"],
alamat: json["alamat"],
no_telp: json["no_telp"],
no_ktp: json["no_ktp"],
no_selular: json["no_selular"],
);
factory Nasabah.fromMap(Map<String, dynamic> map) => Nasabah(
id: map["id"],
nama_debitur: map["nama_debitur"],
alamat: map["alamat"],
no_telp: map["no_telp"],
no_ktp: map["no_ktp"],
no_selular: map["no_selular"],
);
Map<String, dynamic> toJson() => {
"id": id,
"nama_debitur": nama_debitur,
"alamat": alamat,
"no_telp": no_telp,
"no_ktp": no_ktp,
"no_selular": no_selular,
};
#override
String toString() {
return 'Nasabah{id: $id, nama_debitur: $nama_debitur, alamat: $alamat, no_telp: $no_telp, no_ktp: $no_ktp, no_selular: $no_selular}';
}
}
class NasabahResult {
String status;
List<Nasabah> data = new List<Nasabah>();
NasabahResult({
this.status,
this.data,
});
factory NasabahResult.fromJson(Map<String, dynamic> data) => NasabahResult(
status: data["status"],
data: List<Nasabah>.from(
data["data"].map((item) => Nasabah.fromJson(item))),
);
}
NasabahResult nasabahResultFromJson(String jsonData) {
final data = json.decode(jsonData);
return NasabahResult.fromJson(data);
}
String nasabahToJson(Nasabah nasabah) {
final jsonData = nasabah.toJson();
return json.encode(jsonData);
}
Service
import 'package:flutter_auth/Models/nasabah.dart';
import 'dart:convert';
import 'package:http/http.dart' show Client;
class ApiService {
final String baseUrl = '192.168.100.242:8080';
Client client = Client();
Future<List<Nasabah>> getNasabah() async {
final response = await client.get('http://$baseUrl/api/mstdebitur');
print(response.body);
if (response.statusCode == 200) {
final nasabah = (json.decode(response.body) as List)
.map((e) => Nasabah.fromMap(e))
.toList();
return nasabah;
} else {
throw Exception('Failed to load post');
}
}
Future<bool> createNasabah(Nasabah data) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/").toString();
final response = await client.post(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 201) {
return true;
} else {
return false;
}
}
Future<bool> updateNasabah(Nasabah data) async {
String url =
new Uri.http("$baseUrl", "/api/mstdebitur/${data.id}").toString();
final response = await client.put(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> deleteNasabah(int id) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/$id").toString();
final response = await client.delete(url);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
}
Home
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'FormAddNasabah.dart';
import 'ListNasabah.dart';
GlobalKey<ScaffoldState> _scaffoldState = GlobalKey<ScaffoldState>();
// ignore: must_be_immutable
class DataNasabah extends StatefulWidget {
DataNasabah({Key key}) : super(key: key);
String title;
#override
_DataNasabahState createState() => _DataNasabahState();
}
class _DataNasabahState extends State<DataNasabah> {
ApiService apiService;
ListNasabah _listNasabah;
List<Nasabah> data;
#override
void initState() {
super.initState();
apiService = ApiService();
_listNasabah = new ListNasabah(apiService: apiService);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
appBar: AppBar(
title: Text(
'Data Nasabah',
style: TextStyle(color: Colors.white),
),
actions: <Widget>[
GestureDetector(
onTap: () async {
var result = await Navigator.push(
_scaffoldState.currentContext,
MaterialPageRoute(builder: (BuildContext context) {
return FormAddNasabah(nasabah: null);
}),
);
if (result != null) {
setState(() {});
}
},
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
body: _listNasabah.createViewList(),
);
}
}
List
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/FormAddNasabah.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/NasabahHome.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
class ListNasabah {
ApiService apiService;
ListNasabah({this.apiService});
Widget createViewList() {
return SafeArea(
child: FutureBuilder(
future: apiService.getNasabah(),
builder: (BuildContext context, AsyncSnapshot<List<Nasabah>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
'Something wrong with message: ${snapshot.error.toString()}',
textAlign: TextAlign.center,
),
);
} else if (snapshot.connectionState == ConnectionState.done) {
List<Nasabah> nasabah = snapshot.data;
return nasabahListView(nasabah);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Widget nasabahListView(List<Nasabah> listnasabah) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
Nasabah nasabah = listnasabah[index];
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
nasabah.nama_debitur,
style: Theme.of(context).textTheme.bodyText1,
),
Text(nasabah.alamat),
Text(nasabah.no_ktp),
Text(nasabah.no_telp),
Text(nasabah.no_selular),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
apiService.deleteNasabah(nasabah.id).then((value) =>
Navigator.of(context).pushNamed('start'));
},
child: Text(
"Hapus",
style: TextStyle(color: Colors.red),
),
),
FlatButton(
onPressed: () async {
var result = await Navigator.push(context,
MaterialPageRoute(builder: (context) {
return FormAddNasabah(
nasabah: nasabah,
);
}));
},
child: Text(
'Edit',
style: TextStyle(color: Colors.blue),
),
),
],
)
],
),
),
),
);
},
itemCount: listnasabah.length,
),
);
}
}
Form
import 'package:flutter/material.dart';
import 'package:flutter_auth/Models/nasabah.dart';
import 'package:flutter_auth/network/nasabah_service.dart';
import 'package:flutter_auth/screens/Menu/DataNasabah/NasabahHome.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
class FormAddNasabah extends StatefulWidget {
Nasabah nasabah;
FormAddNasabah({this.nasabah});
#override
_FormAddNasabahState createState() => _FormAddNasabahState();
}
class _FormAddNasabahState extends State<FormAddNasabah> {
ApiService apiService;
TextEditingController _contNama = TextEditingController();
TextEditingController _contAlamat = TextEditingController();
TextEditingController _contNoTelp = TextEditingController();
TextEditingController _contNoKtp = TextEditingController();
TextEditingController _contNoSelular = TextEditingController();
#override
void initState() {
super.initState();
apiService = ApiService();
if (widget.nasabah != null) {
_contNama.text = widget.nasabah.nama_debitur;
_contAlamat.text = widget.nasabah.alamat;
_contNoTelp.text = widget.nasabah.no_telp;
_contNoKtp.text = widget.nasabah.no_ktp;
_contNoSelular.text = widget.nasabah.no_selular;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.white),
title: Text(
widget.nasabah == null ? "Tambah Nasabah" : "Edit Nasabah",
style: TextStyle(color: Colors.white),
),
),
body: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
_buildTextField(_contNama, "Nama Nasabah"),
_buildTextField(_contAlamat, "Alamat"),
_buildTextField(_contNoTelp, "No Telp"),
_buildTextField(_contNoKtp, "No KTP"),
_buildTextField(_contNoSelular, "No Selular"),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: RaisedButton(
child: Text(widget.nasabah == null ? "Tambah" : "Edit"),
color: Colors.blue,
onPressed: () {
int id = 0;
if (widget.nasabah != null) {
id = widget.nasabah.id;
}
Nasabah nasabah = Nasabah(
id: id,
nama_debitur: _contNama.text,
alamat: _contAlamat.text,
no_telp: _contNoTelp.text,
no_ktp: _contNoKtp.text,
no_selular: _contNoSelular.text);
if (widget.nasabah == null) {
apiService.createNasabah(nasabah);
} else {
apiService.updateNasabah(nasabah);
}
Navigator.of(context)
.pushNamed('start')
.whenComplete(() => Navigator.pop(context));
},
),
)
],
),
)
],
),
);
}
Widget _buildTextField(TextEditingController _cont, String label) {
return TextField(
controller: _cont,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: label,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
}
Thank you for your attention!

Flutter - Argument type 'List<List<SubCategoriesFolder>> Function(String)' can't be assigned to the parameter type

I'm trying to apply the function compute to get the data from responseJSON.
I used quicktype.io to generate the function for this purpose.
This is what i have done so far:
final subCategoriesFolder = await compute(subCategoriesFolderFromJson, responseJSON);
Error 1:
error: The argument type 'List<List<SubCategoriesFolder>> Function(String)' can't be assigned to the parameter type 'FutureOr<List<List<SubCategoriesFolder>>> Function(dynamic)'. (argument_type_not_assignable at lib\src\ui\pages\subcategories.dart:84)
Error 2:
error: Couldn't infer type parameter 'Q'.
Tried to infer 'dynamic' for 'Q' which doesn't work:
Parameter 'callback' declared as 'FutureOr<R> Function(Q)'
but argument is 'List<List<SubCategoriesFolder>> Function(String)'.
The type 'dynamic' was inferred from:
Parameter 'message' declared as 'Q'
but argument is 'dynamic'.
Consider passing explicit type argument(s) to the generic.
(could_not_infer at lib\src\ui\pages\subcategories.dart:84)
Source:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/foundation.dart';
// import 'dart:isolate';
// import 'package:flutter/foundation.dart';
// import 'catwidget.dart';
// To parse this JSON data, do
//
// final subCategoriesFolder = subCategoriesFolderFromJson(jsonString);
List<List<SubCategoriesFolder>> subCategoriesFolderFromJson(String str) => List<List<SubCategoriesFolder>>.from(json.decode(str).map((x) => List<SubCategoriesFolder>.from(x.map((x) => SubCategoriesFolder.fromJson(x)))));
String subCategoriesFolderToJson(List<List<SubCategoriesFolder>> data) => json.encode(List<dynamic>.from(data.map((x) => List<dynamic>.from(x.map((x) => x.toJson())))));
class SubCategoriesFolder {
SubCategoriesFolder({
this.children,
this.title,
});
List<Child> children;
String title;
factory SubCategoriesFolder.fromJson(Map<String, dynamic> json) => SubCategoriesFolder(
children: List<Child>.from(json["children"].map((x) => Child.fromJson(x))),
title: json["title"],
);
Map<String, dynamic> toJson() => {
"children": List<dynamic>.from(children.map((x) => x.toJson())),
"title": title,
};
}
class Child {
Child({
this.title,
this.uri,
this.iconuri,
this.charset,
});
String title;
String uri;
String iconuri;
String charset;
factory Child.fromJson(Map<String, dynamic> json) => Child(
title: json["title"],
uri: json["uri"],
iconuri: json["iconuri"] == null ? null : json["iconuri"],
charset: json["charset"] == null ? null : json["charset"],
);
Map<String, dynamic> toJson() => {
"title": title,
"uri": uri,
"iconuri": iconuri == null ? null : iconuri,
"charset": charset == null ? null : charset,
};
}
class Subfolder extends StatefulWidget {
#override
SubFolder createState() => SubFolder();
}
class SubFolder extends State<Subfolder> {
Future _fetchJSON() async {
var response = await http.get(
"http://10.0.2.2:5000/subcategories",
headers: {"Accept": "application/json"},
);
if (response.statusCode == 200) {
String responseBody = response.body;
//var responseJSON = json.decode(responseBody);
var responseJSON = await compute(jsonDecode, responseBody);
//final subCategoriesFolder = subCategoriesFolderFromJson(responseJSON);
final subCategoriesFolder = await compute(subCategoriesFolderFromJson, responseJSON);
print(subCategoriesFolder.runtimeType);//THis is not being set, error here
print(subCategoriesFolder);
// name = responseJSON['name'];
// avatar = responseJSON['avatar_url'];
}
return true;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: CupertinoColors.darkBackgroundGray,
body: FutureBuilder(
future: _fetchJSON(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return Center(child: Text('No data'));
} else
return Container(
child: Text(snapshot.data),
);
/*return GridView(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: <Widget>[
for(var item in snapshot.data ) singleCategoryTemp(item)
],
); */
} else if (snapshot.connectionState == snapshot.error) {
return Center(
child: Text('Error: Please try again later')); // error
} else {
return Center(child: CircularProgressIndicator()); // loading
}
}),
);
}
}
You can copy paste run full code below
You can use compute(subCategoriesFolderFromJson, responseBody)
I use nested ListView to show data, you check full code
code snippet
Future<List<List<SubCategoriesFolder>>> _fetchJSON() async {
...
if (response.statusCode == 200) {
String responseBody = response.body;
return compute(subCategoriesFolderFromJson, responseBody);
}
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
List<List<SubCategoriesFolder>> subCategoriesFolderFromJson(String str) =>
List<List<SubCategoriesFolder>>.from(json.decode(str).map((x) =>
List<SubCategoriesFolder>.from(
x.map((x) => SubCategoriesFolder.fromJson(x)))));
String subCategoriesFolderToJson(List<List<SubCategoriesFolder>> data) =>
json.encode(List<dynamic>.from(
data.map((x) => List<dynamic>.from(x.map((x) => x.toJson())))));
class SubCategoriesFolder {
SubCategoriesFolder({
this.children,
this.title,
});
List<Child> children;
String title;
factory SubCategoriesFolder.fromJson(Map<String, dynamic> json) =>
SubCategoriesFolder(
children:
List<Child>.from(json["children"].map((x) => Child.fromJson(x))),
title: json["title"],
);
Map<String, dynamic> toJson() => {
"children": List<dynamic>.from(children.map((x) => x.toJson())),
"title": title,
};
}
class Child {
Child({
this.title,
this.uri,
this.iconuri,
this.charset,
});
String title;
String uri;
String iconuri;
String charset;
factory Child.fromJson(Map<String, dynamic> json) => Child(
title: json["title"],
uri: json["uri"],
iconuri: json["iconuri"] == null ? null : json["iconuri"],
charset: json["charset"] == null ? null : json["charset"],
);
Map<String, dynamic> toJson() => {
"title": title,
"uri": uri,
"iconuri": iconuri == null ? null : iconuri,
"charset": charset == null ? null : charset,
};
}
class Subfolder extends StatefulWidget {
#override
SubFolder createState() => SubFolder();
}
class SubFolder extends State<Subfolder> {
Future<List<List<SubCategoriesFolder>>> _fetchJSON() async {
/*var response = await http.get(
"http://10.0.2.2:5000/subcategories",
headers: {"Accept": "application/json"},
);*/
String jsonString = '''
[[
{
"title" : "1",
"children" : [{
"title":"abc1",
"uri" : "def1",
"iconuri" : "123",
"charset" : "456"
},
{
"title":"abc2",
"uri" : "def1",
"iconuri" : "123",
"charset" : "456"
}]
},
{
"title" : "2",
"children" : [{
"title":"abc2",
"uri" : "def2",
"iconuri" : "789",
"charset" : "321"
}]
}
]]
''';
http.Response response = http.Response(jsonString, 200);
if (response.statusCode == 200) {
String responseBody = response.body;
return compute(subCategoriesFolderFromJson, responseBody);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
//backgroundColor: CupertinoColors.darkBackgroundGray,
body: FutureBuilder(
future: _fetchJSON(),
builder: (BuildContext context,
AsyncSnapshot<List<List<SubCategoriesFolder>>> 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.separated(
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 10,
);
},
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
/* Expanded(
flex: 1, child: Text(snapshot.data[index].toString())),*/
Expanded(
flex: 2,
child: Container(
height: 50,
child: ListView.separated(
separatorBuilder:
(BuildContext context,
int index) {
return SizedBox(
width: 10,
);
},
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount:
snapshot.data[index].length,
itemBuilder: (context, index1) {
return Row(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 120,
child: Column(
children: <Widget>[
Text(
snapshot
.data[index]
[index1]
.title,
style: TextStyle(
color:
Colors.red),
),
Expanded(
child: ListView
.separated(
separatorBuilder:
(BuildContext
context,
int
index) {
return SizedBox(
width:
2,
);
},
shrinkWrap:
true,
scrollDirection:
Axis
.horizontal,
itemCount: snapshot
.data[
index]
[
index1]
.children
.length,
itemBuilder:
(context,
index2) {
return Row(
mainAxisAlignment: MainAxisAlignment
.spaceEvenly,
children: <
Widget>[
Text(snapshot.data[index][index1].children[index2].title,
style: TextStyle(color: Colors.red)),
]);
}),
),
],
),
)
]);
}),
),
)
])
],
);
});
}
}
}));
}
}
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: Subfolder(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Flutter: How to parse mutli array JSON

I have a JSON array - https://jsonplaceholder.typicode.com/users
and my code
final String apiURL = 'https://jsonplaceholder.typicode.com/users';
Future<List<GetUsers>> fetchJSONData() async {
var jsonResponse = await http.get(apiURL);
if (jsonResponse.statusCode == 200) {
final jsonItems = json.decode(jsonResponse.body).cast<Map<String, dynamic>>();
print(jsonItems);
List<GetUsers> usersList = jsonItems.map<GetUsers>((json) {
return GetUsers.fromJson(json);
}).toList();
return usersList;
} else {
throw Exception('Failed to load data from internet');
}
}
How do I parse
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
Street and city
And output it to ListTile
I just know how to output the first level of the array, but I don't understand how to parse the second one
Suppose you want to get the street name of the first user then you can do that by
usersList[0]["address"]["street"]
Here is the complete example:
import "package:flutter/material.dart";
import "dart:convert";
import "package:http/http.dart" as http;
class JsonMultyParse extends StatefulWidget {
#override
_JsonMultyParseState createState() => _JsonMultyParseState();
}
class _JsonMultyParseState extends State<JsonMultyParse> {
final String apiURL = 'https://jsonplaceholder.typicode.com/users';
List<dynamic> users = [];
void fetchJSONData() async {
var jsonResponse = await http.get(apiURL);
if (jsonResponse.statusCode == 200) {
final jsonItems =
json.decode(jsonResponse.body).cast<Map<String, dynamic>>();
print(jsonItems[0]["address"]["street"]);
setState(() {
users = jsonItems;
});
for (dynamic user in users) {
print(user["address"]["street"]);
}
} else {
throw Exception('Failed to load data from internet');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
SizedBox(height: 20),
RaisedButton(
onPressed: fetchJSONData,
child: Text("Fetch Data"),
),
Expanded(
child: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return Card(
child: Container(
height: 50,
padding: const EdgeInsets.all(8.0),
child: Text(
users[index]["address"]["street"],
),
),
);
}),
)
],
),
),
));
}
}
Output: