i've got stuck at this problem for nearly 3 days. Already post it in another questions but, got minus instead an answer.
Let me make it clear the questions.
I would like to put my api data using models into chart flutter, here is my code
First is my model here is my age model
ages.dart
Ages agesFromJson(String str) => Ages.fromJson(json.decode(str));
String agesToJson(Ages data) => json.encode(data.toJson());
class Ages {
Ages({
this.entity,
this.code,
this.year,
this.underAge15,
this.age1564,
this.age65Over,
});
String entity;
String code;
int year;
String underAge15;
String age1564;
String age65Over;
factory Ages.fromJson(Map<String, dynamic> json) => Ages(
entity: json["entity"],
code: json["code"],
year: json["year"],
underAge15: json["under_age_15"],
age1564: json["age_15_64"],
age65Over: json["age_65_over"],
);
Map<String, dynamic> toJson() => {
"entity": entity,
"code": code,
"year": year,
"under_age_15": underAge15,
"age_15_64": age1564,
"age_65_over": age65Over,
};
}
and here i make the ages chart that given me the url from api and put into future builder
ages_chart.dart
class AgeCharts extends StatefulWidget {
final String url;
const AgeCharts({this.url});
#override
_AgeChartsState createState() => _AgeChartsState();
}
class _AgeChartsState extends State<AgeCharts> {
var chart;
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
print(widget.url);
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Japanese Age Working Populations'),
),
body: Container(
height: 400,
child: FutureBuilder<List>(
future: getChartData(widget),
builder: (context, dataapi) {
if (dataapi.hasError) print(dataapi.error);
print(dataapi);
return dataapi.hasData
? ShowChart(
data: dataapi.data,
)
: Center(
child: CircularProgressIndicator(),
);
},
),
),
),
);
}
}
after ages dart, i make a function to get an api.
Future<List> getChartData(widget) async {
final response = await http.get(widget.url);
return json.decode(response.body)['data'];
}
and here is my show chart when i already get an url
class ShowChart extends StatelessWidget {
final List data;
ShowChart({this.data});
static List<charts.Series<Ages, dynamic>> _createSampleData(dataAPI) {
return [
new charts.Series<Ages, dynamic>(
id: 'Desktop',
// colorFn specifies that the line will be blue.
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
// areaColorFn specifies that the area skirt will be light blue.
areaColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
domainFn: (Ages ages, _) => ages.year,
measureFn: (Ages ages, _) => int.parse(ages.underAge15),
data: dataAPI,
),
new charts.Series<Ages, dynamic>(
id: 'Tablet',
// colorFn specifies that the line will be red.
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
// areaColorFn specifies that the area skirt will be light red.
areaColorFn: (_, __) => charts.MaterialPalette.red.shadeDefault.lighter,
domainFn: (Ages ages, _) => ages.year,
measureFn: (Ages ages, _) => int.parse(ages.age1564),
data: dataAPI,
),
new charts.Series<Ages, dynamic>(
id: 'Mobile',
// colorFn specifies that the line will be green.
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
// areaColorFn specifies that the area skirt will be light green.
areaColorFn: (_, __) =>
charts.MaterialPalette.green.shadeDefault.lighter,
domainFn: (Ages ages, _) => ages.year,
measureFn: (Ages ages, _) => int.parse(ages.age65Over),
data: dataAPI,
),
];
}
#override
Widget build(BuildContext context) {
print('showchart');
print(data);
return Container(
child: charts.LineChart(
_createSampleData(data),
defaultRenderer:
new charts.LineRendererConfig(includeArea: true, stacked: true),
animate: true,
),
);
}
}
this is my JSON Structure. but i get the data when using json.decode(response.body)
{
"status": true,
"message": "Chart found",
"data": [
{
"entity": "Japan",
"code": "JPN",
"year": 1950,
"under_age_15": "29288.106",
"age_15_64": "49447.555",
"age_65_over": "4066.423"
},
{
"entity": "Japan",
"code": "JPN",
"year": 1951,
"under_age_15": "29652.515",
"age_15_64": "50461.828",
"age_65_over": "4201.922"
},
]
}
and the i got an error like this
type 'List<dynamic>' is not a subtype of type 'List<Ages>'
help me solve the problem, please
Problems within your code:
You are explicitly casting your series data as charts.Series<Ages, dynamic> while it should be charts.Series<Ages, num>
You are trying to parse double as int. If you want doubles, use double.parse(x) otherwise, double.parse(x).round() will give you a int. (or .floor() or .ceil())
You should probably also specify your domain axis as not being zeroBound:
charts.LineChart(
_createSampleData(data),
defaultRenderer: charts.LineRendererConfig(includeArea: true, stacked: true),
animate: true,
domainAxis: charts.NumericAxisSpec(
tickProviderSpec: charts.BasicNumericTickProviderSpec(zeroBound: false),
),
),
Working Solution
Full source code for easy copy-paste
import 'dart:math' as math;
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Charts Demo',
home:
AgeCharts(url: 'http://udacoding-task-api.herokuapp.com/api/charts'),
),
);
}
// MAIN WIDGET
class AgeCharts extends StatefulWidget {
final String url;
const AgeCharts({this.url});
#override
_AgeChartsState createState() => _AgeChartsState();
}
class _AgeChartsState extends State<AgeCharts> {
var chart;
Future<List<Ages>> getChartData(widget) async {
final response = await http.get(widget.url);
final List<dynamic> jsonData = jsonDecode(response.body)['data'];
return jsonData.map((data) => Ages.fromJson(data)).toList();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Japanese Age Working Populations'),
),
body: Padding(
padding: EdgeInsets.all(8.0),
child: FutureBuilder<List>(
future: getChartData(widget),
builder: (context, dataapi) {
if (dataapi.hasError) print(dataapi.error);
return dataapi.hasData
? ShowChart(data: dataapi.data)
: Center(child: CircularProgressIndicator());
},
),
),
),
);
}
}
// CHART
class ShowChart extends StatelessWidget {
final List<Ages> data;
ShowChart({this.data});
static List<charts.Series<Ages, num>> _createSampleData(dataAPI) {
return [
new charts.Series<Ages, num>(
id: 'underAge15',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
areaColorFn: (_, __) =>
charts.MaterialPalette.blue.shadeDefault.lighter,
domainFn: (Ages ages, _) => ages.year,
measureFn: (Ages ages, _) => double.parse(ages.underAge15).round(),
data: dataAPI,
),
new charts.Series<Ages, num>(
id: 'age1564',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
areaColorFn: (_, __) => charts.MaterialPalette.red.shadeDefault.lighter,
domainFn: (Ages ages, _) => ages.year,
measureFn: (Ages ages, _) => double.parse(ages.age1564).round(),
data: dataAPI,
),
new charts.Series<Ages, num>(
id: 'age65Over',
colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
areaColorFn: (_, __) =>
charts.MaterialPalette.green.shadeDefault.lighter,
domainFn: (Ages ages, _) => ages.year,
measureFn: (Ages ages, _) => double.parse(ages.age65Over).round(),
data: dataAPI,
),
];
}
#override
Widget build(BuildContext context) {
return Container(
child: charts.LineChart(
_createSampleData(data),
defaultRenderer:
new charts.LineRendererConfig(includeArea: true, stacked: true),
animate: true,
domainAxis: charts.NumericAxisSpec(
tickProviderSpec:
charts.BasicNumericTickProviderSpec(zeroBound: false),
),
),
);
}
}
// DOMAIN
class Ages {
Ages({
this.entity,
this.code,
this.year,
this.underAge15,
this.age1564,
this.age65Over,
});
String entity;
String code;
int year;
String underAge15;
String age1564;
String age65Over;
factory Ages.fromJson(Map<String, dynamic> json) => Ages(
entity: json["entity"],
code: json["code"],
year: json["year"],
underAge15: json["under_age_15"],
age1564: json["age_15_64"],
age65Over: json["age_65_over"],
);
Map<String, dynamic> toJson() => {
"entity": entity,
"code": code,
"year": year,
"under_age_15": underAge15,
"age_15_64": age1564,
"age_65_over": age65Over,
};
}
// DATA
math.Random random = math.Random();
final Map<String, dynamic> data = {
"status": true,
"message": "Chart found",
"data": List.generate(
20,
(index) => {
"entity": "Japan",
"code": "JPN",
"year": 1950 + index,
"under_age_15": (25000 + random.nextInt(5000)).toString(),
"age_15_64": (40000 + random.nextInt(5000)).toString(),
"age_65_over": (3000 + random.nextInt(2000)).toString(),
}).toList(),
};
BEFORE ANSWER UPDATE:
Try this:
Future<List<Ages>> getChartData(widget) async {
final response = await http.get(widget.url);
return json.decode(response.body)['data'].map((jsonData) => Ages.fromJson(jsonData)).toList();
}
I'm not 100% sure, since I don't know the structure of your JSON Data.
Related
Flutter, I have This Type of Json from api i want to show multiline chart of every user. Users can increase or decrease on district basis selection inside application? I searched alot from Syncfusion library or from many others but i didnot find any way please help.
**[{"id":"1", "name":"fayyaz","date":"12-1-2021","count":"5"},
{"id":"1", "name":"fayyaz","date":"13-1-2021","count":"7"},
{"id":"1", "name":"fayyaz","date":"14-1-2021","count":"2"},
{"id":"1", "name":"fayyaz","date":"15-1-2021","count":"15"},
{"id":"1", "name":"fayyaz","date":"16-1-2021","count":"10"},
{"id":"2", "name":"ali","date":"14-1-2021","count":"3"},
{"id":"2", "name":"ali","date":"16-1-2021","count":"6"},
{"id":"3", "name":"saad","date":"12-1-2021","count":"1"},
{"id":"3", "name":"saad","date":"13-1-2021","count":"10"},
{"id":"3", "name":"saad","date":"14-1-2021","count":"4"},
{"id":"3", "name":"saad","date":"15-1-2021","count":"3"}];**
SfCartesianChart(
plotAreaBorderWidth: 0,
title: ChartTitle(text: 'Monthly Progress'),
legend: Legend(
isVisible: isCardView ? false : true,
overflowMode: LegendItemOverflowMode.wrap),
primaryXAxis: CategoryAxis(
// Axis will be rendered based on the index values
interval: 1,
labelRotation: 90,
arrangeByIndex: true
),
primaryYAxis: NumericAxis(
edgeLabelPlacement: EdgeLabelPlacement.shift,
// labelFormat: '{value}k',
// minimum: 0,
// maximum: 12,
axisLine: const AxisLine(width: 0),
majorTickLines: const MajorTickLines(color: Colors.transparent)
),
tooltipBehavior: TooltipBehavior(enable: true),
series: <ChartSeries<MonthlyCount, String>>
[
LineSeries<MonthlyCount, String>(
animationDuration: 2500,
width: 2,
name: '',
markerSettings: const MarkerSettings(isVisible: true),
dataSource: chartDataMonthlyCount!,
xValueMapper: (MonthlyCount sales, _) => sales.xaxis,
yValueMapper: (MonthlyCount sales, _) => sales.collectCount,
),
]
),
first use this site quichtype to create a model class from your json. then you can use this model to set data for charts.
after you generate your model class from above site, let's call it User class. you can use it like this.
var json = jsonDecode(PutYourJsonHere);
List<Users> UsersList = json.map((e) => User.fromJson(e)).toList();
We created a sample for your requirement that will parse given JSON data and convert it into multiple lists of a data source based on the id value in the JSON and rendered multiple line series. We have attached the code snippet below and KB for your reference.
KB: https://www.syncfusion.com/kb/11674/how-to-render-a-flutter-chart-using-the-json-data-sfcartesianchart
code snippet
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<SalesData> chartData = [];
#override
void initState() {
loadSalesData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: FutureBuilder(
future: getJsonFromAssets(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return SfCartesianChart(
primaryXAxis: DateTimeAxis(),
series: getLineChart(chartData),
);
} else {
return const CircularProgressIndicator();
}
}));
}
Future<String> getJsonFromAssets() async {
return await rootBundle.loadString('assets/data.json');
}
Future loadSalesData() async {
final String jsonString = await getJsonFromAssets();
final dynamic jsonResponse = json.decode(jsonString);
for (Map<String, dynamic> i in jsonResponse) {
// for(int i = 0; i < chartData.length)
chartData.add(SalesData.fromJson(i));
}
}
List<ChartSeries<SalesData, DateTime>> getLineChart(List<SalesData> data) {
List<ChartSeries<SalesData, DateTime>> series = [];
List<SalesData> _data = [];
List<SalesData> _data1 = [];
List<SalesData> _data2 = [];
for (int i = 0; i < chartData.length; i++) {
chartData[i].id == 1
? _data.add(chartData[i])
: chartData[i].id == 2
? _data1.add(chartData[i])
: _data2.add(chartData[i]);
}
series.addAll([
LineSeries(
dataSource: _data,
xValueMapper: (SalesData data, _) => data.date,
yValueMapper: (SalesData data, _) => data.count),
LineSeries(
dataSource: _data1,
xValueMapper: (SalesData data, _) => data.date,
yValueMapper: (SalesData data, _) => data.count),
LineSeries(
dataSource: _data2,
xValueMapper: (SalesData data, _) => data.date,
yValueMapper: (SalesData data, _) => data.count)
]);
return series;
}
}
class SalesData {
SalesData({
this.id,
this.name,
this.date,
this.count,
});
int? id;
String? name;
DateTime? date;
int? count;
factory SalesData.fromJson(Map<String, dynamic> json) => SalesData(
id: int.parse(json["id"]),
name: json["name"],
date: DateFormat('dd-MM-yyyy').parse(json["date"]),
count: int.parse(json["count"]),
);
}
Here's my code. I have a graph ranging values from 110-130. I need to set my y-axis from 100-140 not from 0-140. Anyone out there , please help me. I have attached my code below. I'm new to flutter.I have used desired tickcount property, it doesn't helped me. Is there any way to set bounds not just for y-axis but both the axis.
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SimpleTimeSeriesChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
SimpleTimeSeriesChart(this.seriesList, {this.animate});
#override
Widget build(BuildContext context) {
return new charts.TimeSeriesChart(
seriesList,
animate: animate,
dateTimeFactory: const charts.LocalDateTimeFactory(),
behaviors: [
charts.SlidingViewport(
charts.SelectionModelType.action,
),
charts.PanBehavior(),
],
primaryMeasureAxis: new charts.NumericAxisSpec(
tickProviderSpec: new charts.BasicNumericTickProviderSpec(
desiredTickCount: 10,
),
),
);
}
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
List<TimeSeriesSales> data1 = [];
List<TimeSeriesSales> data2 = [];
var index = 0;
for (var item in DataMarket) {
data1.insert(index++, TimeSeriesSales(item['date'], item['market']));
}
index = 0;
for (var item in DataMarket) {
data2.insert(index++, TimeSeriesSales(item['date'], item['NAV']));
}
print(data1);
return [
new charts.Series<TimeSeriesSales, DateTime>(
id: 'Sales1',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
measureLowerBoundFn: (TimeSeriesSales sales, _) => sales.sales - 5,
measureUpperBoundFn: (TimeSeriesSales sales, _) => sales.sales + 5,
data: data1,
),
new charts.Series<TimeSeriesSales, DateTime>(
id: 'Sales2',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: data2,
)
];
}
}
/// Sample time series data type.
class TimeSeriesSales {
final DateTime time;
final double sales;
TimeSeriesSales(this.time, this.sales);
}
Add this property to your chart:
primaryMeasureAxis: new charts.NumericAxisSpec(tickProviderSpec:
new charts.BasicNumericTickProviderSpec(zeroBound: false))
Full example:
charts.LineChart(seriesList,primaryMeasureAxis: charts.NumericAxisSpec(
tickProviderSpec:charts.BasicNumericTickProviderSpec(zeroBound: false)))
I have a flutter project where I am using Syncfusion to render the JSON data into charts. I don't get any error when I debug my code but the chart is not rendering when the build is complete. I am not sure if there are mistakes in the codes but it worked fine for other charts.
In addition, some of the reasons I feel responsible for the chart not being rendered could be:
There is too much data to plot. (This may not be the problem since I also tried after reducing data)
The values to plot are too small since they mostly range from some negative values to some positive values and also the values are in decimal (eg 0.7, -0.6, and so on).
These are just my assumption on what could have gone wrong. Please correct me if I am mistaken.
Any ideas to resolve or at least help me understand what is wrong would be great. And yes please help me out :)). Below is the code that I have.
import 'package:flutter/material.dart';
import 'package:fyp/model/rainApiCall.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class Past extends StatefulWidget{
#override
_Past createState() => _Past();
}
class _Past extends State<Past>{
List<String> t = [];
List<String> ampA = [];
List<String> ampB = [];
List<String> ampC = [];
#override
void initState() {
fetchEQData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: FutureBuilder(
future: fetchEQData(),
builder: (context, snapshot){
if(snapshot.hasData) {
var stationID = '4853';
for(int i=0; i<snapshot.data.length; i++){
if(snapshot.data[i].stationId==stationID){
t.add(snapshot.data[i].recordLength);
ampA.add(snapshot.data[i].amplitudemaxa);
ampB.add(snapshot.data[i].amplitudemaxb);
ampC.add(snapshot.data[i].amplitudemaxc);
}
}
return Card(
child: SfCartesianChart(
series: <ChartSeries>[
StackedLineSeries<EqAmpData, double>(
dataSource: getColumnData(t, ampA, ampB, ampC),
dashArray: <double>[5,5],
xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
yValueMapper: (EqAmpData eqdata, _) => int.parse(eqdata.y1),
),
StackedLineSeries<EqAmpData, double>(
dataSource: getColumnData(t, ampA, ampB, ampC),
dashArray: <double>[5,5],
xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
yValueMapper: (EqAmpData eqdata, _) => int.parse(eqdata.y2),
),
StackedLineSeries<EqAmpData, double>(
dataSource: getColumnData(t, ampA, ampB, ampC),
dashArray: <double>[5,5],
xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
yValueMapper: (EqAmpData eqdata, _) => int.parse(eqdata.y3),
),
]
)
);
}
return CircularProgressIndicator();
},
),),);}}
class EqAmpData{
String x;
String y1;
String y2;
String y3;
EqAmpData(this.x, this.y1, this.y2, this.y3);
}
dynamic getColumnData(List xval, List yval1, List yval2, List yval3) {
List rtime = xval;
List y1 = yval1;
List y2 = yval2;
List y3 = yval3;
List<EqAmpData> columnData = <EqAmpData>[];
for (int i = 0; i < rtime.length; i++) {
columnData.add(EqAmpData(rtime[i], y1[i], y2[i], y3[i]));
}
return columnData;
}
Screen after build:
enter image description here
Screenshot of the data I have:
enter image description here
When you define your StackedLineSeries, your yValueMapper should provide double instead of int:
StackedLineSeries<EqAmpData, double>(
dataSource: getColumnData(t, ampA, ampB, ampC),
dashArray: <double>[5, 5],
xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
yValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.y1),
),
Full source code for easy copy-paste
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Charts Demo',
home: Past(),
),
);
}
class Past extends StatefulWidget {
#override
_Past createState() => _Past();
}
class _Past extends State<Past> {
List<String> t = [];
List<String> ampA = [];
List<String> ampB = [];
List<String> ampC = [];
#override
void initState() {
fetchEQData();
super.initState();
}
Future<List<RawData>> fetchEQData() async {
await Future.delayed(Duration(seconds: 2));
return data;
}
StackedLineSeries<EqAmpData, double> prepareSerie({
List<EqAmpData> dataSource,
num Function(EqAmpData, int) yValueMapper,
}) {
return StackedLineSeries<EqAmpData, double>(
dataSource: dataSource,
dashArray: <double>[5, 5],
xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
yValueMapper: yValueMapper,
);
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: FutureBuilder<List<RawData>>(
future: fetchEQData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
snapshot.data
.where((item) => item.stationId == '4853')
.forEach((item) {
t.add(item.recordLength);
ampA.add(item.amplitudemaxa);
ampB.add(item.amplitudemaxb);
ampC.add(item.amplitudemaxc);
});
final dataSource = getColumnData(t, ampA, ampB, ampC);
return Card(
child: SfCartesianChart(
series: <ChartSeries>[
prepareSerie(
dataSource: dataSource,
yValueMapper: (eqdata, _) => double.parse(eqdata.y1),
),
prepareSerie(
dataSource: dataSource,
yValueMapper: (eqdata, _) => double.parse(eqdata.y2),
),
prepareSerie(
dataSource: dataSource,
yValueMapper: (eqdata, _) => double.parse(eqdata.y3),
),
],
),
);
}
return CircularProgressIndicator();
},
),
),
);
}
}
// DOMAIN
class EqAmpData {
final String x;
final String y1;
final String y2;
final String y3;
EqAmpData(this.x, this.y1, this.y2, this.y3);
}
dynamic getColumnData(List rtime, List y1, List y2, List y3) {
return List.generate(
rtime.length,
(i) => EqAmpData(rtime[i], y1[i], y2[i], y3[i]),
);
}
class RawData {
final String stationId;
final String recordLength;
final String amplitudemaxa;
final String amplitudemaxb;
final String amplitudemaxc;
RawData(
this.stationId,
this.recordLength,
this.amplitudemaxa,
this.amplitudemaxb,
this.amplitudemaxc,
);
}
// DATA
final random = math.Random();
final data = List.generate(
100,
(index) => RawData(
"4853",
(index * 0.01).toString(),
((random.nextInt(100) - 50) / 500).toString(),
((random.nextInt(100) - 50) / 1000).toString(),
((random.nextInt(100) - 50) / 1000).toString(),
),
);
i will display linechart from the database using datajson with flutter. but the reference that I can use is hardcode data. Please help
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:charts_flutter/flutter.dart' as charts;
int dataTotal = 0;
class GrafikSpbj extends StatefulWidget {
final List<charts.Series> seriesList;
final bool animate;
GrafikSpbj(this.seriesList, {this.animate});
/// Creates a [LineChart] with sample data and no transition.
factory GrafikSpbj.withSampleData() {
return new GrafikSpbj(
_createSampleData(),
// Disable animations for image tests.
animate: false,
);
}
#override
_GrafikSpbjState createState() => _GrafikSpbjState();
/// Create one series with sample hard coded data.
static List<charts.Series<LinearSales, int>> _createSampleData() {
print(dataTotal);
final desktopSalesData = [
new LinearSales(0, 10),
new LinearSales(1, 50),
new LinearSales(2, 70),
new LinearSales(3, 100),
];
final tableSalesData = [
new LinearSales(0, 20),
new LinearSales(1, 40),
new LinearSales(2, 80),
new LinearSales(3, 100),
];
return [
new charts.Series<LinearSales, int>(
id: 'Desktop',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: desktopSalesData,
),
new charts.Series<LinearSales, int>(
id: 'Tablet',
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: tableSalesData,
),
];
}
}
class _GrafikSpbjState extends State<GrafikSpbj> {
List data;
Timer timer;
int jumlahData = 0;
Future<List> _getData() async {
final response = await http.get("xxxxxxxxxxxxx");
setState(() {
data = json.decode(response.body);
jumlahData =data.length;
print(data[0]['id_spbj']);
print(data[0]['minggu_ke']);
print(data[0]['hasil']);
print(data[0]['target_grafik']);
});
return json.decode(response.body);
}
// makeRequest() async {
// var response = await http.get(
// 'xxxxxxxxxxxxxxxxxxxxxxx',
// headers: {'Accept': 'application/json'},
// );
// setState(() {
// data = json.decode(response.body);
// jumlahData =data.length;
// });
// }
#override
void initState() {
_getData();
dataTotal = jumlahData;
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Text("Input Pelanggan hal 2"),
),
body: Column(
children: <Widget>[
SizedBox(
width: 600.0,
height: 250.0,
child: new charts.NumericComboChart(widget.seriesList,
animate: widget.animate,
defaultRenderer: new charts.LineRendererConfig(),
customSeriesRenderers: [
new charts.PointRendererConfig(customRendererId: 'customPoint')
]),
),
new Text("data"),
new Text("data"),
new Text("data")
],
),
);
}
}
/// Sample linear data type.
class LinearSales {
final int year;
final int sales;
LinearSales(this.year, this.sales);
}
values
[{"id_spbj":"1","minggu_ke":"1","hasil":"13.4353337","target_grafik":"25.00"},{"id_spbj":"1","minggu_ke":"2","hasil":"28.2629147","target_grafik":"25.00"},{"id_spbj":"1","minggu_ke":"3","hasil":"85.3285762","target_grafik":"25.00"},{"id_spbj":"2","minggu_ke":"1","hasil":"32.0184122","target_grafik":"25.00"},{"id_spbj":"2","minggu_ke":"2","hasil":"53.5296934","target_grafik":"25.00"}]
You can use FL_chart plugin library in flutter, where you draw all types of charts.
please find guideline to use FL_Chart
Hi there I am trying to make Piechart base on its example
But I change Just one thing, I changed
final int year
to
final String year
but for domainFn Im getting this error:
{
"resource": "/home/saeb/AndroidStudioProjects/charts/lib/main.dart",
"owner": "dart",
"code": "return_of_invalid_type_from_closure",
"severity": 8,
"message": "The return type 'String' isn't a 'int', as defined by anonymous closure.",
"source": "dart",
"startLineNumber": 36,
"startColumn": 45,
"endLineNumber": 36,
"endColumn": 55,
"tags": []
}
my label should be string not int, how I can do that?
my code:
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class PieOutsideLabelChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
PieOutsideLabelChart(this.seriesList, {this.animate});
factory PieOutsideLabelChart.withSampleData() {
return new PieOutsideLabelChart(
_createSampleData(),
animate: false,
);
}
#override
Widget build(BuildContext context) {
return new charts.PieChart(seriesList,
animate: animate,
defaultRenderer: new charts.ArcRendererConfig(arcRendererDecorators: [
new charts.ArcLabelDecorator(
labelPosition: charts.ArcLabelPosition.outside)
]));
}
static List<charts.Series<LinearSales, int>> _createSampleData() {
final data = [
new LinearSales('a long text', 100),
new LinearSales('even longer text', 75),
new LinearSales('i am long text', 25),
new LinearSales('the longest text ever', 5),
];
return [
new charts.Series<LinearSales, int>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
labelAccessorFn: (LinearSales row, _) => '${row.year}: ${row.sales}',
)
];
}
}
class LinearSales {
final String year;
final int sales;
LinearSales(this.year, this.sales);
}
main(List<String> args) {
runApp(MaterialApp(
title: 'charts',
home: new Scaffold(
appBar: new AppBar(title: new Text("نمودار فلان"),),
body:new ListView(children: <Widget>[
new Card
(child: PieOutsideLabelChart(PieOutsideLabelChart._createSampleData()),)
// ]
// ),
]
)
)
)
);
}
It was syntax problem. my bad :D
I should change my charts.Series to charts.Series<LinearSales, **String**>> from charts.Series<LinearSales, **int**>>
this code works:
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class PieOutsideLabelChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
PieOutsideLabelChart(this.seriesList, {this.animate});
factory PieOutsideLabelChart.withSampleData() {
return new PieOutsideLabelChart(
_createSampleData(),
animate: false,
);
}
#override
Widget build(BuildContext context) {
return new charts.PieChart(seriesList,
animate: animate,
defaultRenderer: new charts.ArcRendererConfig(arcRendererDecorators: [
new charts.ArcLabelDecorator(
labelPosition: charts.ArcLabelPosition.outside)
]));
}
static List<charts.Series<LinearSales, String>> _createSampleData() {
final data = [
new LinearSales('a long text', 100),
new LinearSales('even longer text', 75),
new LinearSales('i am long text', 25),
new LinearSales('the longest text ever', 5),
];
return [
new charts.Series<LinearSales, String>(
id: 'Sales',
domainFn: (LinearSales sales, _) => sales.year,
measureFn: (LinearSales sales, _) => sales.sales,
data: data,
labelAccessorFn: (LinearSales row, _) => '${row.year}',
)
];
}
}
class LinearSales {
final String year;
final int sales;
LinearSales(this.year, this.sales);
}
main(List<String> args) {
runApp(MaterialApp(
title: 'charts',
home: new Scaffold(
appBar: new AppBar(title: new Text("نمودار فلان"),),
body: PieOutsideLabelChart(PieOutsideLabelChart._createSampleData()),)
)
);
}
you can make a class string as domainFn for pie chart in charts_flutter.
it will take some adjustments
Step 1: Add this to your chart so it gonna show label on outside of pie chart
defaultRenderer: new charts.ArcRendererConfig(
arcWidth: 60,
arcRendererDecorators: [new charts.ArcLabelDecorator(
labelPosition: charts.ArcLabelPosition.outside)]
),
Step 2 : Now for customization of those label with string there on property.
which is labelAccessorFn
String datas(int id,int value){
if(id==0){
return value.toString()+":RT";
}else if(id==1){
return value.toString()+":OT";
}
else if(id==2){
return value.toString()+":IT";
}
return [
new charts.Series<VfmProductivityPie, int>(
id: 'Sales',
domainFn: (VfmProductivityPie sales, _) => sales.id,
measureFn: (VfmProductivityPie sales, _) => sales.value,
data: data,
labelAccessorFn: (VfmProductivityPie row, _) =>
// print('object'),
//'${row.id}r: ${row.value}',
datas(row.id,row.value)
)
];
Note: write data function under _createSampleDataworking screenshot of piechart
Its very simple:
set year variable to int again:
final int year
and here use toString() method:
labelAccessorFn: (LinearSales row, _) => '${row.year.toString()}: ${row.sales}',