How to perform a text search over JSON data in Flutter? - json

I am working on an application which requires to fetch some JSON data from firebase storage and then a user can perform a search over it. But, my search query isn't working properly and I get one error when I perform the search multiple times.
I have first uploaded the data to firebase storage and then fetched it. The search is working sometimes only. I cannot figure out what is wrong with the code.
Here is the complete code
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Contacts Demo',
debugShowCheckedModeBanner: false,
home: StorageUpload(),
);
}
}
class StorageUpload extends StatefulWidget {
#override
StorageUploadState createState() => new StorageUploadState();
}
class StorageUploadState extends State<StorageUpload> {
var rows = [];
String query = '';
TextEditingController tc;
#override
void initState() {
super.initState();
tc = TextEditingController();
rows = [
{
'contact_name': 'Test User 1',
'contact_phone': '066 560 4900',
},
{
'contact_name': 'Test User 2',
'contact_phone': '066 560 7865',
},
{
'contact_name': 'Test User 3',
'contact_phone': '906 500 4334',
}
];
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
"Delivero Contacts",
style: new TextStyle(
color: Colors.white,
),
),
),
body: Container(
color: Colors.white,
padding: EdgeInsets.all(10),
child: Stack(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: tc,
decoration: InputDecoration(hintText: 'Search...'),
onChanged: (v) {
setState(() {
query = v;
});
},
),
),
Container(
color: Colors.white,
child: ListView.builder(
shrinkWrap: true,
itemCount: rows.length,
itemBuilder: (con, ind) {
return query.isEmpty
? ListTile(
title: Text(rows[ind]['contact_name']),
subtitle: Text(rows[ind]['contact_phone']),
onTap: () {
setState(() {
tc.text = rows[ind]['contact_name'];
query = rows[ind]['contact_name'];
});
},
)
: rows[ind]['contact_name']
.toString()
.toLowerCase()
.contains(query.toLowerCase()) ||
rows[ind]['contact_phone']
.toString()
.toLowerCase()
.contains(query.toLowerCase())
? ListTile(
title: Text(rows[ind]['contact_name']),
subtitle: Text(rows[ind]['contact_phone']),
onTap: () {
setState(() {
tc.text = rows[ind]['contact_name'];
query = rows[ind]['contact_name'];
});
},
)
: null;
},
),
),
],
),
],
),
),
);
}
}
Here is the error I am getting
════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performLayout():
'package:flutter/src/rendering/sliver_multi_box_adaptor.dart': Failed assertion: line 662 pos 16: 'indexOf(child) == index': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
The relevant error-causing widget was
ListView
lib/main.dart:104
When the exception was thrown, this was the stack
#2 RenderSliverMultiBoxAdaptor.debugAssertChildListIsNonEmptyAndContiguous.<anonymous closure>
package:flutter/…/rendering/sliver_multi_box_adaptor.dart:662
#3 RenderSliverMultiBoxAdaptor.debugAssertChildListIsNonEmptyAndContiguous
package:flutter/…/rendering/sliver_multi_box_adaptor.dart:666
#4 RenderSliverList.performLayout
package:flutter/…/rendering/sliver_list.dart:282
#5 RenderObject.layout
package:flutter/…/rendering/object.dart:1767
#6 RenderSliverEdgeInsetsPadding.performLayout
package:flutter/…/rendering/sliver_padding.dart:135
...
The following RenderObject was being processed when the exception was fired: RenderSliverList#5c228 relayoutBoundary=up17 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
RenderObject: RenderSliverList#5c228 relayoutBoundary=up17 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
needs compositing
parentData: paintOffset=Offset(0.0, 0.0) (can use size)
constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle, scrollOffset: 0.0, remainingPaintExtent: Infinity, crossAxisExtent: 372.7, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: Infinity, remainingCacheExtent: Infinity, cacheOrigin: 0.0)
geometry: SliverGeometry(scrollExtent: 224.0, paintExtent: 224.0, maxPaintExtent: 224.0, cacheExtent: 224.0)
scrollExtent: 224.0
paintExtent: 224.0
maxPaintExtent: 224.0
cacheExtent: 224.0
currently live children: 0 to 3
child with index 0: RenderIndexedSemantics#ea1e2 relayoutBoundary=up18
needs compositing
parentData: index=0; layoutOffset=0.0 (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
semantic boundary
size: Size(372.7, 56.0)
index: 0
child: RenderRepaintBoundary#17c6b relayoutBoundary=up19
needs compositing
parentData: <none> (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
layer: OffsetLayer#34eb7
engine layer: OffsetEngineLayer#a8a79
offset: Offset(0.0, 0.0)
size: Size(372.7, 56.0)
metrics: 0.0% useful (1 bad vs 0 good)
diagnosis: insufficient data to draw conclusion (less than five repaints)
child: RenderSemanticsAnnotations#2ecd5 relayoutBoundary=up20
parentData: <none> (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
size: Size(372.7, 56.0)
child: RenderMouseRegion#9a9a8 relayoutBoundary=up21
parentData: <none> (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
size: Size(372.7, 56.0)
listeners: enter, exit
cursor: SystemMouseCursor(click)
child with index 3: RenderIndexedSemantics#96641 relayoutBoundary=up18
needs compositing
parentData: index=3; layoutOffset=168.0 (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
semantic boundary
size: Size(372.7, 56.0)
index: 3
child: RenderRepaintBoundary#13951 relayoutBoundary=up19
needs compositing
parentData: <none> (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
layer: OffsetLayer#768be
engine layer: OffsetEngineLayer#51b91
offset: Offset(0.0, 168.0)
size: Size(372.7, 56.0)
metrics: 0.0% useful (1 bad vs 0 good)
diagnosis: insufficient data to draw conclusion (less than five repaints)
child: RenderSemanticsAnnotations#77b2c relayoutBoundary=up20
parentData: <none> (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
size: Size(372.7, 56.0)
child: RenderMouseRegion#9ae66 relayoutBoundary=up21
parentData: <none> (can use size)
constraints: BoxConstraints(w=372.7, 0.0<=h<=Infinity)
size: Size(372.7, 56.0)
listeners: enter, exit
cursor: SystemMouseCursor(click)
════════════════════════════════════════════════════════════════════════════════
I am a Flutter noob. How can I perform a full-text search over different JSON field from the data fetched from firebase storage? Any help would be amazing. Thanks for your time!

import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Contacts Demo',
debugShowCheckedModeBanner: false,
home: StorageUpload(),
);
}
}
class StorageUpload extends StatefulWidget {
#override
StorageUploadState createState() => new StorageUploadState();
}
class StorageUploadState extends State<StorageUpload> {
List<Map<String,dynamic>> original=[],duplicate=[];
String query = '';
TextEditingController tc;
StreamController<List<Map<String,dynamic>>> controller = StreamController<List<Map<String,dynamic>>>();
#override
void initState() {
super.initState();
tc = TextEditingController();
original = [
{
'contact_name': 'Test User 1',
'contact_phone': '066 560 4900',
},
{
'contact_name': 'Test User 2',
'contact_phone': '066 560 7865',
},
{
'contact_name': 'Test User 3',
'contact_phone': '906 500 4334',
}
];
duplicate.addAll(original);
controller.sink.add(duplicate);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
"Delivero Contacts",
style: new TextStyle(
color: Colors.white,
),
),
),
body: Container(
color: Colors.white,
padding: EdgeInsets.all(10),
child: Stack(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: tc,
decoration: InputDecoration(hintText: 'Search...'),
onChanged: (v) {
if(v.isEmpty){
duplicate = original;
controller.sink.add(duplicate);
return;
}
//If your data is a Map object you can use toString()
//and avoid checking both fields
duplicate = original.where((m)=>
m['contact_name'].toString().toLowerCase().contains(v.toLowerCase())||
m['contact_phone'].toString().toLowerCase().contains(v.toLowerCase())).toList();
controller.sink.add(duplicate);
},
),
),
Container(
color: Colors.white,
child: StreamBuilder<Object>(
stream: controller.stream,
builder: (context, snapshot) {
return ListView.builder(
shrinkWrap: true,
itemCount: duplicate.length,
itemBuilder: (con, ind) {
return query.isEmpty
? ListTile(
title: Text(duplicate[ind]['contact_name']),
subtitle: Text(duplicate[ind]['contact_phone']),
onTap: () {
setState(() {
tc.text = duplicate[ind]['contact_name'];
query = duplicate[ind]['contact_name'];
});
},
)
: duplicate[ind]['contact_name']
.toString()
.toLowerCase()
.contains(query) ||
duplicate[ind]['contact_phone']
.toString()
.toLowerCase()
.contains(query)
? ListTile(
title: Text(duplicate[ind]['contact_name']),
subtitle: Text(duplicate[ind]['contact_phone']),
onTap: () {
setState(() {
tc.text = duplicate[ind]['contact_name'];
query = duplicate[ind]['contact_name'];
});
},
):null;
},
);
}
),
),
],
),
],
),
),
);
}
#override
void dispose(){
controller?.close();
super.dispose();
}
}

I slightly changed your code to make a working sample.
I added a results List object and I moved the "query.isEmpty" check before the ListView:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Contacts Demo',
debugShowCheckedModeBanner: false,
home: StorageUpload(),
);
}
}
class StorageUpload extends StatefulWidget {
#override
StorageUploadState createState() => new StorageUploadState();
}
class StorageUploadState extends State<StorageUpload> {
List results = [];
var rows = [];
String query = '';
TextEditingController tc;
#override
void initState() {
super.initState();
tc = TextEditingController();
rows = [
{
'contact_name': 'Test User 1',
'contact_phone': '066 560 4900',
},
{
'contact_name': 'Test User 2',
'contact_phone': '066 560 7865',
},
{
'contact_name': 'Test User 3',
'contact_phone': '906 500 4334',
}
];
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
"Delivero Contacts",
style: new TextStyle(
color: Colors.white,
),
),
),
body: Container(
color: Colors.white,
padding: EdgeInsets.all(10),
child: Stack(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: tc,
decoration: InputDecoration(hintText: 'Search...'),
onChanged: (v) {
setState(() {
query = v;
setResults(query);
});
},
),
),
Container(
color: Colors.white,
child: query.isEmpty
? ListView.builder(
shrinkWrap: true,
itemCount: rows.length,
itemBuilder: (con, ind) {
return ListTile(
title: Text(rows[ind]['contact_name']),
subtitle: Text(rows[ind]['contact_phone']),
onTap: () {
setState(() {
tc.text = rows[ind]['contact_name'];
query = rows[ind]['contact_name'];
setResults(query);
});
},
);
},
)
: ListView.builder(
shrinkWrap: true,
itemCount: results.length,
itemBuilder: (con, ind) {
return ListTile(
title: Text(results[ind]['contact_name']),
subtitle: Text(results[ind]['contact_phone']),
onTap: () {
setState(() {
tc.text = results[ind]['contact_name'];
query = results[ind]['contact_name'];
setResults(query);
});
},
);
},
),
),
],
),
],
),
),
);
}
void setResults(String query) {
results = rows
.where((elem) =>
elem['contact_name']
.toString()
.toLowerCase()
.contains(query.toLowerCase()) ||
elem['contact_phone']
.toString()
.toLowerCase()
.contains(query.toLowerCase()))
.toList();
}
}

Related

Flutter: How to navigate to specific tabbar with FutureBuilder?

I made a simple store app where I put data in a json file. I've managed to call the data into the Tabbar & TabbarView by FutureBuilder. Also I put the list of these products in a drawer. I want if I click on one of the product names from Drawer, it will navigate to specific TabBar respective IDs.
I've done this trick before, but only on static pages, not FutureBuilder like this. I really appreciate any help
HomePage.dart
import 'dart:convert';
import 'package:contoh_tabbar_json/model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class HomePage extends StatefulWidget {
const HomePage({Key key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
Future<List<Product>> _getProduct() async {
final dataString = await rootBundle.loadString('assets/myproduct.json');
final List<dynamic> json = jsonDecode(dataString);
final products = <Product>[];
for (var v in json) {
products.add(Product.fromJson(v));
}
return products;
}
#override
void initState() {
_getProduct();
super.initState();
}
#override
void dispose() {
super.dispose();
}
Product product;
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Product>>(
future: _getProduct(),
builder: (context, mydata) {
if (mydata.hasData) {
List<Tab> tabs = <Tab>[];
for (int index = 0; index < mydata.data.length; index++) {
tabs.add(Tab(
child: Text(
mydata.data[index].title,
),
));
}
return DefaultTabController(
length: mydata.data.length,
child: Scaffold(
endDrawer: Drawer(
child: SingleChildScrollView(
physics: const ScrollPhysics(),
child: Column(
children: [
Center(
child: Container(
height: 100,
alignment: Alignment.center,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(50),
),
),
child: const Text("Product List",
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w700,
),
textAlign: TextAlign.center),
),
),
),
//
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: mydata.data.length,
itemBuilder: (BuildContext context, index) {
return ListTile(
dense: true,
title: Text(mydata.data[index].title, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w500)),
onTap: () {
Navigator.pop(context);
},
);
}),
const SizedBox(height: 70),
],
),
),
),
appBar: AppBar(
title: const Text("My Store"),
bottom: TabBar(
isScrollable: true,
tabs: tabs,
),
),
body: FutureBuilder<List<Product>>(
future: _getProduct(),
builder: (context, mydata) {
if (mydata.hasData) {
List<Widget> tabs = <Widget>[];
for (int index = 0; index < mydata.data.length; index++) {
tabs.add(Tab(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 30),
Text(
mydata.data[index].title,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 30),
Text(mydata.data[index].title),
const SizedBox(height: 30),
Text(mydata.data[index].description),
const SizedBox(height: 30),
Text(mydata.data[index].category),
],
),
),
),
));
}
return TabBarView(
children: tabs,
);
}
return Container();
},
),
),
);
}
return Scaffold(
body: Center(child: Text(mydata.hasError ? mydata.error.toString() : "Loading...")),
);
},
);
}
}
Model
import 'dart:convert';
List<Product> productFromJson(String str) =>
List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
class Product {
Product({
this.id,
this.title,
this.description,
this.category,
});
final int id;
final String title;
final String description;
final String category;
factory Product.fromJson(Map<String, dynamic> json) => Product(
id: json["id"],
title: json["title"],
description: json["description"],
category: json["category"],
);
String getTitle() {
return title;
}
String getDescription() {
return description;
}
String getCategory() {
return category;
}
}
Mungkin bisa dicek pada github saya :
https://github.com/kuldii/navigate_drawer_tabbar

i have a problem showing the json data in the drop-down list flutter

this is my first flutter JSON example, I tried to fetch data from the JSON link and display it on a drop-down list.
I am getting the response on the console but the drop-down list doesn't work
any help, please?......................................................................................................................................................................................................................................................................................................................
this is the body
ERROR
this is my code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
_getfamilyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<String>(
value: _myfamily,
iconSize: 30,
icon: (null),
style: TextStyle(
color: Colors.black54,
fontSize: 16,
),
hint: Text('Select family'),
onChanged: (String newValue) {
setState(() {
_myfamily = newValue;
print(_myfamily);
});
},
items: familysList?.map((item) {
return new DropdownMenuItem(
child: new Text(item['firsName']),
);
})?.toList() ??
[],
),
),
),
),
],
),
),
],
),
);
}
List familysList;
String _myfamily;
String familyInfoUrl =
'http://10.0.2.2:3000/genocheck/user/getmembrefamille/f1';
Future<String> _getfamilyList() async {
await http.get(familyInfoUrl).then((response) {
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data['famille'];
});
});
}
}
as I see the problem is in your JSON response
famille is the first element ,
the list of data is the second element
however in your code familysList = data['famille'];
you are assuming that famille is a key and the list of data is the value and this is not correct
so answer is one of those
1 - make your asignment like familysList = data[0];
2- change your json to be {"famille" :[{"id":8654,"firstname":"some name"]"}
The error caused because although data's type is List that can access by 'int' index, you access like Map.
data['famille']
As your data body, data[0] is 'famille' and data[1] is data what you want.
data[1] is
[
{
"_id": "",
"firstName": "",
}
]
You can copy paste run full code below
Step 1: data[0] is String famille, data[1] is List you want
familysList = data[1];
Step 2: firsName is typo you need firstName
Step 3: DropdownMenuItem need value attribute
items: familysList?.map((item) {
return DropdownMenuItem<String>(
child: Text("${item["firstName"]}"),
value: item["firstName"],
);
})?.toList() ??
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
_getfamilyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<String>(
value: _myfamily,
iconSize: 30,
icon: (null),
style: TextStyle(
color: Colors.black54,
fontSize: 16,
),
hint: Text('Select family'),
onChanged: (String Value) {
setState(() {
_myfamily = Value;
print("_myfamily $_myfamily");
});
},
items: familysList?.map((item) {
//print(item["firstName"]);
return DropdownMenuItem<String>(
child: Text("${item["firstName"]}"),
value: item["firstName"],
);
})?.toList() ??
[],
),
),
),
),
],
),
),
],
),
);
}
List familysList;
String _myfamily;
String familyInfoUrl =
'http://10.0.2.2:3000/genocheck/user/getmembrefamille/f1';
Future<String> _getfamilyList() async {
String jsonString = '''
[
"famille",
[
{
"_id" : "123",
"firstName":"abc"
},
{
"_id" : "456",
"firstName":"def"
}
]
]
''';
http.Response response = http.Response(jsonString, 200);
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data[1];
});
/*await http.get(familyInfoUrl).then((response) {
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data[1];
});
});*/
}
}
full code 2 for new question
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class UserElement {
UserElement({
this.id,
this.firstName,
});
String id;
String firstName;
factory UserElement.fromJson(Map<String, dynamic> json) => UserElement(
id: json["_id"] == null ? null : json["_id"],
firstName: json["firstName"] == null ? null : json["firstName"],
);
Map<String, dynamic> toJson() => {
"_id": id == null ? null : id,
"firstName": firstName == null ? null : firstName,
};
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
_getfamilyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<UserElement>(
value: _myfamily,
iconSize: 30,
icon: (null),
style: TextStyle(
color: Colors.black54,
fontSize: 16,
),
hint: Text('Select family'),
onChanged: (UserElement Value) {
setState(() {
_myfamily = Value;
print("_myfamily ${_myfamily.firstName}");
});
},
items: familysList?.map((item) {
return DropdownMenuItem<UserElement>(
child: Text("${item.id} ${item.firstName}"),
value: item,
);
})?.toList() ??
[],
),
),
),
),
],
),
),
],
),
);
}
List<UserElement> familysList = [];
UserElement _myfamily;
String familyInfoUrl =
'http://10.0.2.2:3000/genocheck/user/getmembrefamille/f1';
Future<String> _getfamilyList() async {
String jsonString = '''
[
"famille",
[
{
"_id" : "123",
"firstName":"abc"
},
{
"_id" : "456",
"firstName":"abc"
}
]
]
''';
http.Response response = http.Response(jsonString, 200);
var data = json.decode(response.body);
//print(data);
setState(() {
List<dynamic> listData = data[1];
for (var i = 0; i < listData.length; i++) {
familysList.add(UserElement.fromJson(listData[i]));
}
});
/*await http.get(familyInfoUrl).then((response) {
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data['famille'];
});
});*/
}
}

Flutter get snapshot.data[1] in future builder

I have the following code
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';
class MyData {
String title;
String days;
String words;
String rep;
String gender;
var username;
MyData({this.gender, this.title, this.days, this.words, this.rep, this.username,
});
}
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
Future<List<String>> _future;
Future<List<String>> _car;
List<GlobalKey<FormState>> formKeys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>()
];
String _key = "786465659081B207EB5BF1EF9AF7552A6";
String _api = "https://10.0.2.2/api/";
Future<void> senddata(List<String> username) async {
final response = await http.post(
_api + "insert_data.php?key=" + _key, body: {
"username": username,
});
var resp = jsonDecode(response.body);
print(resp.toString());
}
Future<List<String>> getData() async {
var url = _api + "get_data.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['username'] as String).toList();
}
Future<List<String>> getCar() async {
var url = _api + "get_car.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['plate'] as String).toList();
}
#override
void initState() {
super.initState();
_future = getData();
_car = getCar();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
#override
Widget build(BuildContext context) {
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
}
void _submitDetails(List<String> username) {
final FormState formState = _formKey.currentState;
final FormBuilderState fbKeyState = _fbKey.currentState;
/*
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
*/
if (!fbKeyState.validate()) {
showSnackBarMessage('Please enter correct data');
senddata(username);
} else {
showSnackBarMessage('Saved');
formState.save();
senddata(username);
print("Name: $username");
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
}
}
return FutureBuilder<List<String>>(
future: Future.wait([_future, _car]),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final steps = [
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: FormBuilderCheckboxList(
decoration:
InputDecoration(labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data[0]
.map((languages) => FormBuilderFieldOption(
value: languages, child: Text("$languages")))
.toList(),
),
),
],
),
),
),
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: FormBuilderCheckboxList(
decoration:
InputDecoration(labelText: "Cars"),
attribute: "cars",
initialValue: ["BM-WD01"],
options: snapshot.data[1]
.map((car) => FormBuilderFieldOption(
value: car, child: Text("$car")))
.toList(),
),
),
],
),
),
),
];
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
physics: ClampingScrollPhysics(),
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if (formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
//
RaisedButton(
color: Colors.red,
child: Text("Forward",
style: TextStyle(color: Colors.white)),
onPressed: onStepContinue,
),
SizedBox(width: 15,),
RaisedButton(
color: Colors.red,
child: Text(
"Back", style: TextStyle(color: Colors.white)),
onPressed: onStepCancel,
),
],
);
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
onPressed: () {
var submitDetails = _submitDetails;
submitDetails(snapshot.data);
},
color: Colors.lightGreen,
),
]),
));
} else {
return CircularProgressIndicator();
}
}
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "test",),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
MyAppScreenMode createState() => MyAppScreenMode();
}
class MyAppScreenMode extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Test stepper'),
),
body: new StepperBody(),
));
}
}
I want to display multiple lists from mySQL, the first function _future works fine, but when I replace future: _future to
future: Future.wait([_future, _car]),
I get an
The element type 'Future<List>' can't be assigned to the list
type 'Future'
I have tried lots of other solutions but none of them works to use snapshot.data[0], snapshot.data1 and so on for more queries and data to display from different tables.
Can't get to work with more futurebuilders which would be even easier for each step own, but then I get
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: FutureBuilder<List>(
future: _future,
// ignore: missing_return
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: FormBuilderCheckboxList(
decoration:
InputDecoration(
labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data
.map((gender) =>
FormBuilderFieldOption(
value: gender, child: Text("$gender")))
.toList(),
),
),
],
);
}
}
),
),
),
];
Any help would be appreciated.
The working solution for the question. If there is any better way feel free to post :)
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';
class MyData {
String title;
String days;
String words;
String rep;
String gender;
var username;
MyData(
{this.gender, this.title, this.days, this.words, this.rep, this.username,
});
}
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
Future<List<String>> _future;
Future<List<String>> _getcar;
List<GlobalKey<FormState>> formKeys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>()
];
String _key = "786465659081B207EB5BF1EF9AF7552A6";
String _api = "https://10.0.2.2/api/";
Future<void> senddata() async {
final response = await http.post(
_api + "insert_data.php?key=" + _key, body: {
});
var resp = jsonDecode(response.body);
print(resp.toString());
}
Future<List<String>> getData() async {
var url = _api + "get_data.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['username'] as String).toList();
}
Future<List<String>> getCar() async {
var url = _api + "get_car.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['plate'] as String).toList();
}
Widget getdis2(BuildContext context) {
return FutureBuilder<List<String>>(
future: _getcar, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
FormBuilderCheckboxList(
decoration:
InputDecoration(
labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data
.map((gender) =>
FormBuilderFieldOption(
value: gender, child: Text("$gender")))
.toList(),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
},
);
}
Widget getdis(BuildContext context) {
return FutureBuilder<List<String>>(
future: _future, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
FormBuilderCheckboxList(
decoration:
InputDecoration(
labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data
.map((gender) =>
FormBuilderFieldOption(
value: gender, child: Text("$gender")))
.toList(),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
},
);
}
#override
void initState() {
super.initState();
_future = getData();
_getcar = getCar();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
#override
Widget build(BuildContext context) {
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
}
void _submitDetails() {
final FormState formState = _formKey.currentState;
final FormBuilderState fbKeyState = _fbKey.currentState;
/*
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
*/
if (!fbKeyState.validate()) {
showSnackBarMessage('Please enter correct data');
senddata();
} else {
showSnackBarMessage('Saved');
formState.save();
senddata();
print("Name: ");
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
}
}
final steps = [
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: getdis(context),
),
),
Step(
title: const Text('Cars'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: getdis2(context),
),
),
];
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
physics: ClampingScrollPhysics(),
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if (formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
//
RaisedButton(
color: Colors.red,
child: Text("Forward",
style: TextStyle(color: Colors.white)),
onPressed: onStepContinue,
),
SizedBox(width: 15,),
RaisedButton(
color: Colors.red,
child: Text(
"Back", style: TextStyle(color: Colors.white)),
onPressed: onStepCancel,
),
],
);
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
onPressed: () {
var submitDetails = _submitDetails;
submitDetails();
},
color: Colors.lightGreen,
),
]),
));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "test",),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
MyAppScreenMode createState() => MyAppScreenMode();
}
class MyAppScreenMode extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Test stepper'),
),
body: new StepperBody(),
));
}
}
Im not sure about this, but in my understanding, a FutureBuilder expects exactly 1 future. the returned value of this future is accessable with "snapshot.data".
If you need to wait for multiple futures to resolve, I propose you use multiple FutureBuilders.
Another way would be to use Future.wait() somewhere else and return all required data as one Furure from there.

In flutter, how would I save the TextBox input from generated textboxes?

Below is my full code, the only thing you need to do to run it is adding "http: any" to dependencies in pubspec.yaml.
What the code does is grab JSON input from source, and for each entry in the json feed create a card. Now for each question, I want the user to provide an answer, so when I add the button to the bottom, it brings up a popup box showing the answers (which I'll later post back to my server).
It would look something like:
Q1: "three"
Q2: "thirty"
Q3: "Some movie character"
Q4: "Walter White"
(I'll do the validation to my answers later)
My json is posted below the code.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Question>> fetchQuestions(http.Client client) async {
final response =
await client.get('https://jsonblob.com/api/jsonBlob/a5885973-7f02-11ea-b97d-097037d3b153');
// Use the compute function to run parsePhotos in a separate isolate
return compute(parseQuestion, response.body);
}
// A function that will convert a response body into a List<Photo>
List<Question> parseQuestion(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Question>((json) => Question.fromJson(json)).toList();
}
class Question {
final int id;
final String question;
final String answer;
Question({this.id, this.question, this.answer});
factory Question.fromJson(Map<String, dynamic> json) {
return Question(
id: json['id'] as int,
question: json['question'] as String,
answer: json['answer'] as String
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final appTitle = 'Isolate Demo';
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Padding(
child: FutureBuilder<List<Question>>(
future: fetchQuestions(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? QuestionList(questions: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),
padding: EdgeInsets.fromLTRB(1.0, 10.0, 1.0, 10.0),
),
);
}
}
class QuestionList extends StatelessWidget {
final List<Question> questions;
QuestionList({Key key, this.questions}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: questions.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Container(
constraints: BoxConstraints.expand(
height: Theme.of(context).textTheme.display1.fontSize * 1.1 +
200.0,
),
color: Colors.blueGrey,
alignment: Alignment.center,
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text(questions[index].id.toString()),
subtitle: Text(questions[index].question),
),
new TextFormField(
decoration: new InputDecoration(
labelText: "Answer Question",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(
),
),
),
validator: (val) {
if(val.length==0) {
return "Type your answer here";
}else{
return null;
}
},
keyboardType: TextInputType.text,
style: new TextStyle(
fontFamily: "Poppins",
),
),
/*
// make buttons use the appropriate styles for cards
ButtonBar(
children: <Widget>[
RaisedButton(
color: Colors.lightBlue,
hoverColor: Colors.blue,
child: const Text('Open'),
onPressed: () {/* ... */},
),
],
),
*/
],
),
)),
],
);
},
);
}
}
[
{
"id" : 1,
"question" : "what is one plus two",
"answer": "three"
},
{
"id" : 2,
"question" : "what is five times 6",
"answer": "thirty"
},
{
"id" : 3,
"question" : "Who said show me the money",
"answer": "Cuba Gooding Jnr"
},
{
"id" : 4,
"question" : "who said I am the danger",
"answer": "Walter White"
}
]
Consider attaching a TextEditingController to the TextFormField through the controller property. You can access the text currently in the TextField using the controller's text field.

How to generate a list of cards based on the number of items in json file

I use the following code to generate 10 predefined cards on a flutter screen which doesn't change:
List cards = new List.generate(10, (i)=>new QuestionCard()).toList();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('My First App'),
backgroundColor:new Color(0xFF673AB7),
),
body: new Container(
child: new ListView(
children: cards,
)
)
);
}
}
class QuestionCard extends StatefulWidget {
#override
_QuestionCardState createState() => _QuestionCardState();
}
class _QuestionCardState extends State<QuestionCard> {
#override
Widget build(BuildContext context) {
return Container(
child: Card(
borderOnForeground: true,
color: Colors.green,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
trailing: Icon(Icons.album),
title: Text('Q1'),
subtitle: Text('What is the name of this location?'),
),
new TextFormField(
decoration: new InputDecoration(
labelText: "Answer Question",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(
),
),
//fillColor: Colors.green
),
validator: (val) {
if(val.length==0) {
return "Type your answer here";
}else{
return null;
}
},
keyboardType: TextInputType.text,
style: new TextStyle(
fontFamily: "Poppins",
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('Save'),
onPressed: () {/* ... */},
),
],
),
],
),
),
);
}
}
My json is simple (questions.json):
{
"Questions":
[
{
"id" : 1,
"quest" : ["question one"]
},
{
"id" : 2,
"quest" : ["question two", "question three"]
},
{
"id" : 3,
"quest" : ["question four"]
},
{
"id" : 4,
"quest" : ["question five", "question six", "question seven"]
}
]
}
So I have 2 questions I need to solve:
1. If I have more than 1 question I'll need to add an additional text box for a response for which I'll use a different card type, 2, 3, 4 max, which I'll need to define once.
But my real question here:
How do I generate the list based on the json response:
Future _loadQuestionAssets() async
{
return await rootBundle.loadString('assets/questions.json');
}
Future loadQuestion() async{
String jsonString = await _loadQuestionAssets();
final jsonResponse = json.decode(jsonString);
Questions question = new Questions.fromJson(jsonResponse);
//List cards = new List.generate(length, generator)
}
try this:
class MyFirstApp extends StatefulWidget{
#override
createState()=> new _appState();
}
class _appState extends State<MyFirstApp>{
List _displayData;
//assuming that you saved your json file in your assets folder
loadJson() async {
String data = await rootBundle.loadString('assets/json/questions.json');
jsonResult = json.decode(data);
print(jsonResult);
setState((){
_displayData = jsonResult["Questions"];
});
}
#override
void initState(){
super.initState();
loadJson();
}
#override
Widget build(BuildContext context){
return Scaffold(
appbar: Appbar(
title: Text("My APP")
),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: _displayData == null ? Center(child: CircularProgressIndicator()) :
ListView.builder(
itemcount: _displayData.length,
itembuilder: (context, index){
return Container(
width: MediaQuery.of(context).size.width,
height: 80,
margin: EdgeInsets.only(bottom: 5),
child: Text(_displayData[index]["id"])
);
}
)
)
);
}
}