Reputation: 27
I want to convert this API to multiable lists
it should act like the image below
https://i.sstatic.net/10Qld.png Any help will be appreciated
I want to convert
1-categories.name toList
2-categories.children.name toList
3-categories.children.children_lv.name toList
4-categories.children.name.children_lv.children.name toList
and want to make every dropdown dependant to the previous one Example: the user should select from categories.name toList to be able to choose from 2-categories.children.name toList
API
"categories": [
{
"category_id": "1841",
"name": "Cars",
"children": [
{
"name": "Car1",
"category_id": "1845",
"children_lv": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
"column": "1",
{
"name": "Car2",
"category_id": "1846",
"children_lv": [
{
"name": "Car2_1",
"category_id": "1847",
"children_lv": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
},
{
"name": "Car2_2",
"category_id": "1848",
"children_lv": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
}
],
}
],
},
{
"category_id": "1842",
"name": "Properties",
"children": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
"column": "1",
},
{
"category_id": "1843",
"name": "Machines",
"children": [
{
"name": "",
"category_id": "",
"children_lv": "",
}
],
"column": "1",
},
{
"category_id": "1844",
"name": "Electronics",
"children": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
"column": "1",
}
]
}```
the lists that should be converted are category, children and the other children_lv
**Model has been made with app.quicktype.io and it works **
Upvotes: 2
Views: 233
Reputation: 2529
I did an example, the same as your example, but changed some names to make it clear to you
First, you need to create the Classes that you need like this:
Example of only one class ***** the same thing applies to the other classes *****
myCategory.dart
import 'package:flutterapp/myCategory1.dart';
import 'package:json_annotation/json_annotation.dart';
part 'myCategory.g.dart';
@JsonSerializable()
class MyCategory {
String name;
List<MyCategory1> children1;
MyCategory({this.name,this.children1});
factory MyCategory.fromJson(Map<String, dynamic> json) =>
_$MyCategoryFromJson(json);
Map<String, dynamic> toJson() => _$MyCategoryToJson(this);
}
myCategory.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'myCategory.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
MyCategory _$MyCategoryFromJson(Map<String, dynamic> json) {
return MyCategory(
name: json['name'] as String,
children1: (json['children1'] as List)
?.map((e) => e == null
? null
: MyCategory1.fromJson(e as Map<String, dynamic>))
?.toList());
}
Map<String, dynamic> _$MyCategoryToJson(MyCategory instance) =>
<String, dynamic>{'name': instance.name, 'children1': instance.children1};
the myCategory.g.dart
is generic file by json_serializable,
pubspec.yaml
dependencies:
flutter:
sdk: flutter
json_serializable: ^3.4.1
dev_dependencies:
build_runner: ^1.10.0
Where I generate it with the following command
flutter pub run build_runner build --delete-conflicting-outputs
Of course, you can use another method, but I prefer this method
Now let's take a look at the most important thing:
class CategoriesWidget extends StatefulWidget {
@override
_CategoriesWidgetState createState() => new _CategoriesWidgetState();
}
class _CategoriesWidgetState extends State<CategoriesWidget> {
List<MyCategory> myNestedList;
MyCategory _selectedMyCategory;
MyCategory1 _selectedMyCategory1;
MyCategory2 _selectedMyCategory2;
@override
void initState() {
super.initState();
myNestedList =
(map['categories'] as List).map((e) => MyCategory.fromJson(e)).toList();
}
Map<String, dynamic> map = {
'categories': [
{
"name": '1',
"children1": [
{"name": '1-1'},
{
"name": '1-2',
'children2': [
{'name': '1-2-1'},
{'name': '1-2-2'}
]
}
]
},
{
"name": '2',
"children1": [
{"name": '2-1'},
{
"name": '2-2',
'children2': [
{'name': '2-2-1'},
{'name': '2-2-2'}
]
}
]
}
]
};
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: AppBar(
title: Text("Dropdown Categories"),
centerTitle: true,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey, width: 0.5)),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
margin: EdgeInsets.all(8),
child: DropdownButton(
isDense: true,
isExpanded: true,
hint: Text('My categories'),
underline: Container(),
items: myNestedList.map((item) {
return DropdownMenuItem(
value: item,
child: Text(item.name),
);
}).toList(),
value: _selectedMyCategory,
onChanged: (value) {
setState(() {
_selectedMyCategory = value;
if (_selectedMyCategory1 != null) {
_selectedMyCategory1 = _selectedMyCategory.children1
.firstWhere(
(element) => element == _selectedMyCategory1,
orElse: () => null);
}
});
},
),
),
_selectedMyCategory?.children1 != null &&
_selectedMyCategory.children1.length > 0
? Container(
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey, width: 0.5)),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
margin: EdgeInsets.all(8),
child: DropdownButton(
isDense: true,
isExpanded: true,
hint: Text('My categories 1'),
underline: Container(),
value: _selectedMyCategory1,
items: _selectedMyCategory.children1.map((item) {
return DropdownMenuItem(
value: item,
child: Text(item.name),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedMyCategory1 = value;
if (_selectedMyCategory2 != null) {
_selectedMyCategory2 =
_selectedMyCategory1.children2.firstWhere(
(element) =>
element == _selectedMyCategory2,
orElse: () => null);
}
});
},
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text('My categories 1')),
),
_selectedMyCategory1?.children2 != null &&
_selectedMyCategory1.children2.length > 0
? Container(
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey, width: 0.5)),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
margin: EdgeInsets.all(8),
child: DropdownButton(
isDense: true,
isExpanded: true,
hint: Text('My categories 2'),
underline: Container(),
items: _selectedMyCategory1.children2.map((item) {
return DropdownMenuItem(
value: item,
child: Text(item.name),
);
}).toList(),
value: _selectedMyCategory2,
onChanged: (value) {
setState(() {
_selectedMyCategory2 = value;
});
},
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text('My categories 2')),
),
],
),
),
);
}
}
I tried it myself, and here is the result:
Good luck
Upvotes: 1
Reputation: 31371
List<T> list = (map['list'] as List).map<T>((e)=>T.fromMap(e));
Try with this, but replace T with Model.
Also it should have fromMap
function, to parse Map<String,dynamic>
to your model.
else use normal constructors
((e)=>T(a:e['a'], b:e['b']);
Here is an example:
class Model {
final String a;
final String b;
Model({this.a,this.b});
factory Model.fromMap(Map<String,dynamic> map) =>
Model(
a: map['a'],
b: map['b']
);
}
This is a model with fromMap
function. You can get that function easy with plugins for AndroidStudio or VSCode.
The one I use for android studio is called DartDataClass
.
Now when you have json with lists =>
{ list : [
{ "a":"we","b":"try"},
{ "a":"as","b":"dfg"},
]}
You can use code above to parse that JSON if you have create the model for it.
Map<String,dynamic> json = jsonDecode(jsonSource);
List<Model> list = (json['list'] as List).map<Model>((e)=>Model.fromMap(e)).toList();
Upvotes: 1