Reputation: 463
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:
tabX
has a value, if tabY
== null will not includetabY
has a value, if tabX
== null will not includeSo 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')))
],
)
],);
}
}
Upvotes: 1
Views: 786
Reputation: 3326
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
],
)
Upvotes: 1
Reputation: 789
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.
Upvotes: 0