I have 2 JSON file like this:
json1 (API):
[
{
"json1Language": "English",
"json1Icon": "https://www.countryflags.io/gb/flat/64.png",
"json1Code": "en"
},
{
"json1Language": "French",
"json1Icon": "https://www.countryflags.io/fr/flat/64.png",
"json1Code": "fr"
},
{
"json1Language": "Spanish",
"json1Icon": "https://www.countryflags.io/es/flat/64.png",
"json1Code": "es"
}
]
json2 (API):
[
{
"json2Country": "Canada",
"json2Continent": "North American",
"json2Language": [
"French",
"English"
]
},
{
"json2Country": "Mexico",
"json2Continent": "North American",
"json2Language": [
"Spanish",
"English"
]
},
{
"json2Country": "United Kingdom",
"json2Continent": "Europe",
"json2Language": [
"English"
]
},
{
"json2Country": "France",
"json2Continent": "Europe",
"json2Language": [
"French"
]
},
{
"json2Country": "Spain",
"json2Continent": "Europe",
"json2Language": [
"Spanish"
]
}
]
I tried to show the data of json1Code from Json1, it shows an error Flutter: RangeError (index): Invalid value: Valid value range is empty: -1 for a few seconds then shows the data correctly, I'm not sure where I did wrong
I think maybe something wrong in the Build class:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following RangeError was thrown building Builder(dirty):
RangeError (index): Invalid value: Valid value range is empty: -1
The relevant error-causing widget was:
Builder file:///D:/Flutter/Test/load_data/lib/json2_page3.dart:80:17
When the exception was thrown, this was the stack:
#0 List.[] (dart:core-patch/growable_array.dart:177:60)
#1 _ShowContinentState.build.<anonymous closure> (package:load_data/json2_page3.dart:83:38)
#2 Builder.build (package:flutter/src/widgets/basic.dart:7183:48)
#3 StatelessElement.build (package:flutter/src/widgets/framework.dart:4644:28)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4570:15)
please help me, this is main file
import 'package:flutter/material.dart';
import 'package:load_data/model/json2_model.dart';
import 'package:load_data/service/json1_service.dart';
import 'package:load_data/service/json2_service.dart';
import 'model/json1_model.dart';
class Json2Page3 extends StatefulWidget {
#override
_Json2Page3State createState() => _Json2Page3State();
}
class _Json2Page3State extends State<Json2Page3> {
List<Json2> json2 = [];
List<String> _continent = [];
#override
void initState() {
super.initState();
setState(() {
Json2Services.getData().then((data) {
setState(() {
json2 = data;
_continent = json2.map<String>((x) => x.json2Continent).toSet().toList();
});
});
});
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: _continent.length,
child: Scaffold(
appBar: AppBar(
title: Text('Page 2'),
bottom: TabBar(tabs: _continent.map((String name) => Tab(text: name)).toList()),
),
body: TabBarView(
children: _continent.map((String name) {
return ShowContinent(
json2: List<Json2>.from(json2)..retainWhere((e) => e.json2Continent == name),
);
}).toList()),
));
}
}
class ShowContinent extends StatefulWidget {
final List<Json2> json2;
ShowContinent({this.json2});
#override
_ShowContinentState createState() => _ShowContinentState(json2);
}
class _ShowContinentState extends State<ShowContinent> {
final List<Json2> json2;
List<Json1> json1 = [];
_ShowContinentState(this.json2);
#override
void initState() {
super.initState();
Json1Services.getData().then((data) {
setState(() {
json1 = data;
});
});
}
#override
Widget build(BuildContext context) {
return Column(
children: [
for (Json2 j2 in json2)
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(j2.json2Country.toUpperCase()),
for (int i = 0; i < j2.json2Language.length; i++)
Builder(
builder: (_) {
int index = json1.indexWhere((e) => e.json1Language == j2.json2Language[i]);
return Row(
children: [
Image.network(json1[index].json1Icon),
Text(json1[index].json1Code),
],
);
},
)
],
),
],
);
}
}
You can copy paste run full code below
You can use addPostFrameCallback and bool isLoading to check loading status
when isLoading == true, return CircularProgressIndicator()
code snippet
bool isLoading = true;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Json1Services.getData().then((data) {
setState(() {
json1 = data;
isLoading = false;
});
});
});
}
#override
Widget build(BuildContext context) {
return isLoading
? Center(child: CircularProgressIndicator())
: Column(
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
List<Json2> json2FromJson(String str) =>
List<Json2>.from(json.decode(str).map((x) => Json2.fromJson(x)));
String json2ToJson(List<Json2> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
List<Json1> json1FromJson(String str) =>
List<Json1>.from(json.decode(str).map((x) => Json1.fromJson(x)));
String json1ToJson(List<Json1> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Json1 {
Json1({
this.json1Language,
this.json1Icon,
this.json1Code,
});
String json1Language;
String json1Icon;
String json1Code;
factory Json1.fromJson(Map<String, dynamic> json) => Json1(
json1Language: json["json1Language"],
json1Icon: json["json1Icon"],
json1Code: json["json1Code"],
);
Map<String, dynamic> toJson() => {
"json1Language": json1Language,
"json1Icon": json1Icon,
"json1Code": json1Code,
};
}
class Json2 {
Json2({
this.json2Country,
this.json2Continent,
this.json2Language,
});
String json2Country;
String json2Continent;
List<String> json2Language;
factory Json2.fromJson(Map<String, dynamic> json) => Json2(
json2Country: json["json2Country"],
json2Continent: json["json2Continent"],
json2Language: List<String>.from(json["json2Language"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"json2Country": json2Country,
"json2Continent": json2Continent,
"json2Language": List<dynamic>.from(json2Language.map((x) => x)),
};
}
class Json2Services {
static Future<List<Json2>> getData() async {
await Future.delayed(Duration(seconds: 5), () {});
String jsonString = '''
[
{
"json2Country": "Canada",
"json2Continent": "North American",
"json2Language": [
"French",
"English"
]
},
{
"json2Country": "Mexico",
"json2Continent": "North American",
"json2Language": [
"Spanish",
"English"
]
},
{
"json2Country": "United Kingdom",
"json2Continent": "Europe",
"json2Language": [
"English"
]
},
{
"json2Country": "France",
"json2Continent": "Europe",
"json2Language": [
"French"
]
},
{
"json2Country": "Spain",
"json2Continent": "Europe",
"json2Language": [
"Spanish"
]
}
]
''';
return Future.value(json2FromJson(jsonString));
}
}
class Json1Services {
static Future<List<Json1>> getData() async {
await Future.delayed(Duration(seconds: 5), () {});
String jsonString = '''
[
{
"json1Language": "English",
"json1Icon": "https://www.countryflags.io/gb/flat/64.png",
"json1Code": "en"
},
{
"json1Language": "French",
"json1Icon": "https://www.countryflags.io/fr/flat/64.png",
"json1Code": "fr"
},
{
"json1Language": "Spanish",
"json1Icon": "https://www.countryflags.io/es/flat/64.png",
"json1Code": "es"
}
]
''';
return Future.value(json1FromJson(jsonString));
}
}
class Json2Page3 extends StatefulWidget {
#override
_Json2Page3State createState() => _Json2Page3State();
}
class _Json2Page3State extends State<Json2Page3> {
List<Json2> json2 = [];
List<String> _continent = [];
#override
void initState() {
super.initState();
setState(() {
Json2Services.getData().then((data) {
setState(() {
json2 = data;
_continent =
json2.map<String>((x) => x.json2Continent).toSet().toList();
});
});
});
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: _continent.length,
child: Scaffold(
appBar: AppBar(
title: Text('Page 2'),
bottom: TabBar(
tabs:
_continent.map((String name) => Tab(text: name)).toList()),
),
body: TabBarView(
children: _continent.map((String name) {
return ShowContinent(
json2: List<Json2>.from(json2)
..retainWhere((e) => e.json2Continent == name),
);
}).toList()),
));
}
}
class ShowContinent extends StatefulWidget {
final List<Json2> json2;
ShowContinent({this.json2});
#override
_ShowContinentState createState() => _ShowContinentState(json2);
}
class _ShowContinentState extends State<ShowContinent> {
final List<Json2> json2;
List<Json1> json1 = [];
_ShowContinentState(this.json2);
bool isLoading = true;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Json1Services.getData().then((data) {
setState(() {
json1 = data;
isLoading = false;
});
});
});
}
#override
Widget build(BuildContext context) {
return isLoading
? Center(child: CircularProgressIndicator())
: Column(
children: [
for (Json2 j2 in json2)
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(j2.json2Country.toUpperCase()),
for (int i = 0; i < j2.json2Language.length; i++)
Builder(
builder: (_) {
int index = json1.indexWhere(
(e) => e.json1Language == j2.json2Language[i]);
return Row(
children: [
Image.network(json1[index].json1Icon),
Text(json1[index].json1Code),
],
);
},
)
],
),
],
);
}
}
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: Json2Page3(),
);
}
}
When build() is called, json data is not ready.
So you need to fix code asynchronous.
I suggest one solution 'FutureBuilder'
https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
Related
I have a JSON file like this:
[
{
"name": "A",
"tabX": ["AX1","AX2"],
"tabY": null
},
{
"name": "B",
"tabX": null,
"tabY": ["BY1","BY2"]
},
{
"name": "C",
"tabX": ["CX1","CX2"],
"tabY": ["CY1","CY2"]
}
]
I want to create 3 TabView:
The "All" tab shows all
Tab "TabX" will show the elements that tabX has a value, if tabY == null will not include
Tab "TabY" will show the elements that tabY has a value, if tabX == null will not include
So please help me, this is full code:
import 'package:flutter/material.dart';
import 'dart:convert';
List<Json> jsonFromJson(String str) => List<Json>.from(json.decode(str).map((x) => Json.fromJson(x)));
String jsonToJson(List<Json> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Json {
Json({
this.name,
this.tabX,
this.tabY,
});
String name;
List<String> tabX;
List<String> tabY;
factory Json.fromJson(Map<String, dynamic> json) => Json(
name: json["name"] == null ? null : json["name"],
tabX: json["tabX"] == null ? null : List<String>.from(json["tabX"].map((x) => x)),
tabY: json["tabY"] == null ? null : List<String>.from(json["tabY"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"name": name == null ? null : name,
"tabX": tabX == null ? null : List<dynamic>.from(tabX.map((x) => x)),
"tabY": tabY == null ? null : List<dynamic>.from(tabY.map((x) => x)),
};
}
class JsonServices {
static Future<List<Json>> getData() {
String jsonString = '''
[
{
"name": "A",
"tabX": ["AX1","AX2"],
"tabY": null
},
{
"name": "B",
"tabX": null,
"tabY": ["BY1","BY2"]
},
{
"name": "C",
"tabX": ["CX1","CX2"],
"tabY": ["CY1","CY2"]
}
]
''';
return Future.value(jsonFromJson(jsonString));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Json> _json = [];
#override
void initState() {
super.initState();
setState(() {
JsonServices.getData().then((data) {
setState(() {
_json = data;
});
});
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(text: 'ALL'),
Tab(text: 'TabX'),
Tab(text: 'TabY'),
],
),
),
body: TabBarView(children: [
Tab(child: TabItemWidget(j: _json,),),
Tab(text: 'TabX'), // pls help
Tab(text: 'TabY'), // pls help
],),
),
),
);
}
}
class TabItemWidget extends StatelessWidget {
final List<Json> j;
const TabItemWidget({Key key, this.j}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(children: [
for(Json j in j)
Row(
children: [
Expanded(child: Text('${j.name}: ')),
if(j.tabX != null) Expanded(child: Text(j.tabX.reduce((value, element) => '$value - $element'))),
if(j.tabY != null) Expanded(child: Text(j.tabY.reduce((value, element) => '$value - $element')))
],
)
],);
}
}
You can filter the list before passing in:
// Only when tabX != null
_json.where((element) => element.tabX != null).toList()
// Only when tabY != null
_json.where((element) => element.tabY != null).toList()
To display only the appropriate value for that tab, we can use an enum and pass it in. It's always a good idea to use enum when we have more than 2 modes of display
enum DisplayMode { all, onlyX, onlyY }
The TabItemWidget would now be:
class TabItemWidget extends StatelessWidget {
final List<Json> j;
final DisplayMode mode;
const TabItemWidget({Key key, this.j, this.mode = DisplayMode.all})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
for (Json j in j)
Row(
children: [
Expanded(child: Text('${j.name}: ')),
if (j.tabX != null && !(mode == DisplayMode.onlyY))
Expanded(
child: Text(j.tabX
.reduce((value, element) => '$value - $element'))),
if (j.tabY != null && !(mode == DisplayMode.onlyX))
Expanded(
child: Text(
j.tabY.reduce((value, element) => '$value - $element')))
],
)
],
);
}
}
The TabBarView would now be:
body: TabBarView(
children: [
Tab(
child: TabItemWidget(
j: _json,
),
),
Tab(
child: TabItemWidget(
j: _json.where((element) => element.tabX != null).toList(),
mode: DisplayMode.onlyX,
),
),
// pls help
Tab(
child: TabItemWidget(
j: _json.where((element) => element.tabY != null).toList(),
mode: DisplayMode.onlyY,
),
),
// pls help
],
)
Result:
This code is not beautiful but it works (null safety):
import 'package:flutter/material.dart';
import 'dart:convert';
List<Json> jsonFromJson(String str) => List<Json>.from(json.decode(str).map((x) =>
Json.fromJson(x)));
String jsonToJson(List<Json> data) => json.encode(List<dynamic>.from(data.map((x) =>
x.toJson())));
class Json {
Json({
this.name,
this.tabX,
this.tabY,
});
String? name;
List<String>? tabX;
List<String>? tabY;
factory Json.fromJson(Map<String, dynamic> json) => Json(
name: json["name"] == null ? null : json["name"],
tabX: json["tabX"] == null ? null : List<String>.from(json["tabX"].map((x) =>
x)),
tabY: json["tabY"] == null ? null : List<String>.from(json["tabY"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"name": name == null ? null : name,
"tabX": (tabX == null)? null : List<dynamic>.from(tabX!.map((x) => x)),
"tabY": (tabY == null) ? null : List<dynamic>.from(tabY!.map((x) => x)),
};
}
class JsonServices {
static Future<List<Json>> getData() {
String jsonString = '''
[
{
"name": "A",
"tabX": ["AX1","AX2"],
"tabY": null
},
{
"name": "B",
"tabX": null,
"tabY": ["BY1","BY2"]
},
{
"name": "C",
"tabX": ["CX1","CX2"],
"tabY": ["CY1","CY2"]
}
]
''';
return Future.value(jsonFromJson(jsonString));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Json> _json = [];
#override
void initState() {
super.initState();
setState(() {
JsonServices.getData().then((data) {
setState(() {
_json = data;
});
});
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(text: 'ALL'),
Tab(text: 'TabX'),
Tab(text: 'TabY'),
],
),
),
body: TabBarView(children: [
Tab(child: TabItemWidget(j: _json,),),
Tab(child: TabItemWidget2(j: _json,),), // pls help
Tab(child: TabItemWidget3(j: _json,),), // pls help
],),
),
),
);
}
}
class TabItemWidget extends StatelessWidget {
final List<Json> j;
TabItemWidget({Key? key, required this.j}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(children: [
for(Json j in j)
Row(
children: [
Expanded(child: Text('${j.name}: ')),
if(j.tabX != null) Expanded(child: Text(j.tabX!.reduce((value, element) =>
'$value - $element'))),
if(j.tabY != null) Expanded(child: Text(j.tabY!.reduce((value, element) =>
'$value - $element')))
],
)
],);
}
}
class TabItemWidget2 extends StatelessWidget {
final List<Json> j;
const TabItemWidget2({Key? key, required this.j}) : super(key: key);
#override
Widget build(BuildContext context) {
print(j.where((element) => element.tabX != null).toString());
var jForTabX = j.where((element) => element.tabX != null);
return Column(children: [
for(Json j in jForTabX)
Row(
children: [
Expanded(child: Text('${j.name}: ')),
if(j.tabX != null && j.tabY == null) Expanded(child:
Text(j.tabX!.reduce((value, element) => '$value - $element'))),
if(j.tabY != null) Expanded(child: Text(j.tabX!.reduce((value, element) =>
'$value - $element')))
],
)
],);
}
}
class TabItemWidget3 extends StatelessWidget {
final List<Json> j;
const TabItemWidget3({Key? key, required this.j}) : super(key: key);
#override
Widget build(BuildContext context) {
var jForTabY = j.where((element) => element.tabY != null);
return Column(children: [
for(Json j in jForTabY)
Row(
children: [
Expanded(child: Text('${j.name}: ')),
if(j.tabX != null && j.tabX == null) Expanded(child:
Text(j.tabX!.reduce((value, element) => '$value - $element'))),
if(j.tabY != null) Expanded(child: Text(j.tabY!.reduce((value, element) =>
'$value - $element')))
],
)
],);
}
}
You can improve que quality of this code.
I have a list of maps list this:
var taxesGroups = [
{
"name": "Spain",
"taxes": [
{"name": "IVA", "percentage": "21"},
{"name": "IRPF", "percentage": "19"},
]
},
{
"name": "UK",
"taxes": [
{"name": "VAT", "percentage": "20"},
]
}
];
var dropdownValue = taxesGroups[0]["name"];
So far I tried this:
DropdownButton(
value: dropdownValue,
items: taxesGroups.map((taxGroup) {
return DropdownMenuItem<String>(
value: taxGroup["name"],
child: Text(taxGroup["name"]),
);
}).toList(),
onChanged: (taxGroup) {
setState(() {
dropdownValue = taxGroup;
});
},
),
I get this error:
type 'List' is not a subtype of type
'List<DropdownMenuItem>'
I guess it's related to the info I want to display in the dropdown (Spain, UK) and what I get when choose an option but I don't figure it out
You have mismatched the taxesGroups map.
I tried to recreate your use case with this and it works.
class MyApp2 extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp2> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var taxesGroups = [
{
"name": "Spain",
"taxes": [
{"name": "IVA", "percentage": "21"},
{"name": "IRPF", "percentage": "19"},
]
},
{
"name": "UK",
"taxes": [
{"name": "VAT", "percentage": "20"},
]
}
];
var dropdownValue;
#override
void initState() {
dropdownValue = taxesGroups[0];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("AppBar"),
),
body: DropdownButton(
value: dropdownValue['name'],
items: taxesGroups.map((taxGroup) {
return DropdownMenuItem<String>(
value: taxGroup["name"],
child: Text(taxGroup["name"]),
);
}).toList(),
onChanged: (taxGroup) {
print('taxGroup $taxGroup');
taxesGroups.map((e) {
if (e["name"] == taxGroup)
setState(() {
dropdownValue = e;
});
});
},
),
);
}
}
Add type as DropownMenuItem for map
DropdownButton(
value: dropdownValue,
items: taxesGroups.map<DropdownMenuItem>((taxGroup) {
return DropdownMenuItem<String>(
value: taxGroup["name"],
child: Text(taxGroup["name"]),
);
}).toList(),
onChanged: (taxGroup) {
setState(() {
dropdownValue = taxGroup;
});
},
),
I have 2 JSON file:
Json1 file:
[
{
"json1language": "English"
},
{
"json1language": "French"
},
{
"json1language": "Spanish"
}
]
Json2 file:
[
{
"json2country": "Canada",
"json2languages": [
{
"json2language": "English"
},
{
"json2language": "French"
}
]
},
{
"json2country": "Mexico",
"json2languages": [
{
"json2language": "English"
},
{
"json2language": "Spanish"
}
]
},
{
"json2country": "France",
"json2languages": [
{
"json2language": "French"
}
]
}
]
I want that when I click on json1language => showDialog show json2country and json2language that match the condition json2language == json1language
Example: click "English" => show json2country: "Canada"; json2language: "English","French" & json2country: "Mexico"; json2language: "English","Spanish" (because json2language contains "English")
So pls help me, this is the main file
import 'package:flutter/material.dart';
import 'dart:convert';
List<Json1> json1FromJson(String str) => List<Json1>.from(json.decode(str).map((x) => Json1.fromJson(x)));
String json1ToJson(List<Json1> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Json1 {
Json1({
this.json1Language,
});
String json1Language;
factory Json1.fromJson(Map<String, dynamic> json) => Json1(
json1Language: json["json1language"],
);
Map<String, dynamic> toJson() => {
"json1language": json1Language,
};
}
List<Json2> json2FromJson(String str) => List<Json2>.from(json.decode(str).map((x) => Json2.fromJson(x)));
String json2ToJson(List<Json2> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Json2 {
Json2({
this.json2Country,
this.json2Languages,
});
String json2Country;
List<Json2Language> json2Languages;
factory Json2.fromJson(Map<String, dynamic> json) => Json2(
json2Country: json["json2country"],
json2Languages: List<Json2Language>.from(json["json2languages"].map((x) => Json2Language.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"json2country": json2Country,
"json2languages": List<dynamic>.from(json2Languages.map((x) => x.toJson())),
};
}
class Json2Language {
Json2Language({
this.json2Language,
});
String json2Language;
factory Json2Language.fromJson(Map<String, dynamic> json) => Json2Language(
json2Language: json["json2language"],
);
Map<String, dynamic> toJson() => {
"json2language": json2Language,
};
}
class Json1Services {
static Future<List<Json1>> getData() {
String jsonString = '''
[
{
"json1language": "English"
},
{
"json1language": "French"
},
{
"json1language": "Spanish"
}
]
''';
return Future.value(json1FromJson(jsonString));
}
}
class Json2Services {
static Future<List<Json2>> getData() {
String jsonString = '''
[
{
"json2country": "Canada",
"json2languages": [
{
"json2language": "English"
},
{
"json2language": "French"
}
]
},
{
"json2country": "Mexico",
"json2languages": [
{
"json2language": "English"
},
{
"json2language": "Spanish"
}
]
},
{
"json2country": "France",
"json2languages": [
{
"json2language": "French"
}
]
}
]
''';
return Future.value(json2FromJson(jsonString));
}
}
class Json extends StatefulWidget {
#override
_JsonState createState() => _JsonState();
}
class _JsonState extends State<Json> {
List<Json1> _json1 = [];
List<Json2> _json2 = [];
#override
void initState() {
super.initState();
setState(() {
Json1Services.getData().then((data) {
setState(() {
_json1 = data;
});
});
Json2Services.getData().then((data) {
setState(() {
_json2 = data;
});
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (Json1 j1 in _json1)
RaisedButton(
child: Text(j1.json1Language),
onPressed: () => showDialog(
context: context,
builder: (_) {
return AlertDialog(
content: null,
);
}))
],
),
));
}
}
You can copy paste run full code below
code snippet
filtered = [];
_json2.forEach((element) {
for (int i = 0;
i < element.json2Languages.length;
i++) {
if (element.json2Languages[i].json2Language ==
j1.json1Language) {
filtered.add(element);
}
}
});
...
return AlertDialog(
content: SizedBox(
width: 300,
height: 70,
child: Row(
children: [
Expanded(
flex: 2,
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
for (int i = 0;
i < filtered.length;
i++)
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
filtered[i].json2Country,
),
for (int j = 0;
j <
filtered[i]
.json2Languages
.length;
j++)
Column(children: [
Text(filtered[i]
.json2Languages[j]
.json2Language)
]),
],
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
List<Json1> json1FromJson(String str) =>
List<Json1>.from(json.decode(str).map((x) => Json1.fromJson(x)));
String json1ToJson(List<Json1> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Json1 {
Json1({
this.json1Language,
});
String json1Language;
factory Json1.fromJson(Map<String, dynamic> json) => Json1(
json1Language: json["json1language"],
);
Map<String, dynamic> toJson() => {
"json1language": json1Language,
};
}
List<Json2> json2FromJson(String str) =>
List<Json2>.from(json.decode(str).map((x) => Json2.fromJson(x)));
String json2ToJson(List<Json2> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Json2 {
Json2({
this.json2Country,
this.json2Languages,
});
String json2Country;
List<Json2Language> json2Languages;
factory Json2.fromJson(Map<String, dynamic> json) => Json2(
json2Country: json["json2country"],
json2Languages: List<Json2Language>.from(
json["json2languages"].map((x) => Json2Language.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"json2country": json2Country,
"json2languages":
List<dynamic>.from(json2Languages.map((x) => x.toJson())),
};
}
class Json2Language {
Json2Language({
this.json2Language,
});
String json2Language;
factory Json2Language.fromJson(Map<String, dynamic> json) => Json2Language(
json2Language: json["json2language"],
);
Map<String, dynamic> toJson() => {
"json2language": json2Language,
};
}
class Json1Services {
static Future<List<Json1>> getData() {
String jsonString = '''
[
{
"json1language": "English"
},
{
"json1language": "French"
},
{
"json1language": "Spanish"
}
]
''';
return Future.value(json1FromJson(jsonString));
}
}
class Json2Services {
static Future<List<Json2>> getData() {
String jsonString = '''
[
{
"json2country": "Canada",
"json2languages": [
{
"json2language": "English"
},
{
"json2language": "French"
}
]
},
{
"json2country": "Mexico",
"json2languages": [
{
"json2language": "English"
},
{
"json2language": "Spanish"
}
]
},
{
"json2country": "France",
"json2languages": [
{
"json2language": "French"
}
]
}
]
''';
return Future.value(json2FromJson(jsonString));
}
}
class Json extends StatefulWidget {
#override
_JsonState createState() => _JsonState();
}
class _JsonState extends State<Json> {
List<Json1> _json1 = [];
List<Json2> _json2 = [];
#override
void initState() {
super.initState();
setState(() {
Json1Services.getData().then((data) {
setState(() {
_json1 = data;
});
});
Json2Services.getData().then((data) {
setState(() {
_json2 = data;
});
});
});
}
List<Json2> filtered = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (Json1 j1 in _json1)
RaisedButton(
child: Text(j1.json1Language),
onPressed: () => showDialog(
context: context,
builder: (_) {
filtered = [];
_json2.forEach((element) {
for (int i = 0;
i < element.json2Languages.length;
i++) {
if (element.json2Languages[i].json2Language ==
j1.json1Language) {
filtered.add(element);
}
}
});
return AlertDialog(
content: SizedBox(
width: 300,
height: 70,
child: Row(
children: [
Expanded(
flex: 2,
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
for (int i = 0;
i < filtered.length;
i++)
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
filtered[i].json2Country,
),
for (int j = 0;
j <
filtered[i]
.json2Languages
.length;
j++)
Column(children: [
Text(filtered[i]
.json2Languages[j]
.json2Language)
]),
],
)
],
),
)
],
),
),
);
}))
],
),
));
}
}
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: Json(),
);
}
}
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),
),
);
}
}
I have 2 JSON file:
json1: String people name (API)
[
{
"name": "Oliver"
},
{
"name": "George"
},
{
"name": "Harry"
}
]
json2: String outfit and an array of people who fit that outfit (API)
[
{
"outfit": "T-shirt",
"fit": [
"Oliver",
"George"
]
},
{
"outfit": "Hat",
"fit": [
"George",
"Harry"
]
},
{
"outfit": "Jacket",
"fit": [
"Harry"
]
}
]
I want that when clicking on the name of the person => show outfits that fit them
Ex. George fits a T-shirt and a hat
So pls help me, this is the main file:
import 'package:ask/model/page1_model.dart';
import 'package:ask/model/page2_model.dart';
import 'package:ask/services/json2_service.dart';
import 'package:ask/services/json1_service.dart';
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
List<Json1> _json1 = [];
List<Json2> _json2 = [];
#override
void initState() {
super.initState();
Json1Services.getData().then((data) {
setState(() {
_json1 = data;
});
});
Json2Services.getData().then((data) {
setState(() {
_json2 = data;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('List Name')),
body: ListView.builder(
itemCount: _json1.length,
itemBuilder: (BuildContext context, int index) {
Json1 json1 = _json1[index];
return Column(children: [
InkWell(
child: Text(json1.name),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(title: Text('${json1.name} fits:')),
body: ShowWhatFit(json2: List<Json2>.from(_json2)..retainWhere((element) => element.fit[index] == json1.name)), // I think this line is not right
))))
]);
},
));
}
}
class ShowWhatFit extends StatelessWidget {
final List<Json2> json2;
ShowWhatFit({this.json2});
#override
Widget build(BuildContext context) {
return Row(
children: [
for (int i = 0; i < json2.length; i++) Text(json2[i].outfit),
],
);
}
}
..............................................................................
List<Json2>.from(_json2)..retainWhere((element) => element.fit[index] == json1.name))
retainWhere will check every element and keep only those where the condition is true. the problem is element.fit[index] == json1.name just check the element at index index of the list fit and compares it with the name json1.name, doesn't really check if the name is in the list fit. Try:
List<Json2>.from(_json2)..retainWhere((element) => element.fit.contains(json1.name)))
That will iterate every elemnt in json2, then check if the list fit contains an equal object json1.name and returns true if there is one, otherwise false
How do I populate this JSON list into dropdown button?
{
"status": true,
"message": "success",
"data": {
"list": [
{
"idattribute": "2",
"attrName": "BBQ"
},
{
"idattribute": "1",
"attrName": "FRUIT JUICE"
}
]
}
}
class _YourPageState extends State<YourPage> {
Map yourJson = {
"status": true,
"message": "success",
"data": {
"list": [
{"idattribute": "2", "attrName": "BBQ"},
{"idattribute": "1", "attrName": "FRUIT JUICE"}
]
}
};
int _value = 1;
List<DropdownMenuItem<int>> _menuItems;
#override
void initState() {
super.initState();
List dataList = yourJson["data"]["list"];
_menuItems = List.generate(
dataList.length,
(i) => DropdownMenuItem(
value: int.parse(dataList[i]["idattribute"]),
child: Text("${dataList[i]["attrName"]}"),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: DropdownButton<int>(
items: _menuItems,
value: _value,
onChanged: (value) => setState(() => _value = value),
),
),
);
}
}