syncfusion / flutter-examples

This repository contains the Syncfusion Flutter UI widgets examples and the guide to use them.
Other
1.96k stars 776 forks source link

initiate series as invisible. but the legend is "visible" and after click legend, all series is visible. #821

Closed azizainunnajib closed 11 months ago

azizainunnajib commented 1 year ago

i have series with 5 SpLineArea. the series is like this.

var series = [SplineAreaSeries<ChartDataView, DateTime>( dataSource: _chartData, isVisible: **true**, name: 'Load Consumption', xValueMapper: (ChartDataView data, _) => data.period, yValueMapper: (ChartDataView data, _) => data.loadConsumption), SplineAreaSeries<ChartDataView, DateTime>( dataSource: _chartData, isVisible: **false**, name: 'Export to Grid', xValueMapper: (ChartDataView data, _) => data.period, yValueMapper: (ChartDataView data, _) => data.loadConsumption), SplineAreaSeries<ChartDataView, DateTime>( dataSource: _chartData, isVisible: **false**, name: 'Export to Grid', xValueMapper: (ChartDataView data, _) => data.period, yValueMapper: (ChartDataView data, _) => data.loadConsumption), SplineAreaSeries<ChartDataView, DateTime>( dataSource: _chartData, isVisible: **false**, name: 'Export to Grid', xValueMapper: (ChartDataView data, _) => data.period, yValueMapper: (ChartDataView data, _) => data.loadConsumption), SplineAreaSeries<ChartDataView, DateTime>( dataSource: _chartData, isVisible: **false**, name: 'Export to Grid', xValueMapper: (ChartDataView data, _) => data.period, yValueMapper: (ChartDataView data, _) => data.loadConsumption) ]

I set it only first data is visible first.

at the first load is fine, the first data is only data visible. but the legend is not grey. then when I click legend, all series is showing.

here I attach the video. https://github.com/syncfusion/flutter-examples/assets/22388427/3dc89b8b-8e48-4201-8b3c-6522a28c8459

*note I digging some code in library, is it maybe because this code? seems wrong because the variable seriesVisible is not calculate in that method. here I attach part of library's code. Screenshot 2023-09-26 223308

sfHariHaraSudhan commented 1 year ago

Hi @azizainunnajib,

We understand that you need to render only the first series at load time and to render all the other respective series while toggling the legend using the legendItemBuilder property. While using the legendItemBuilder property all the series will be in visible at load time itself but it might appear only the first series is rendering as you have given same series name except for the first series and same y values for all the series based on the provided code snippet.

However, we would like to let you know that currently, the legend template doesn't consider the series visibility. So, we have achieved your requirement with the help of a list of Boolean values to represent the series visibility and wrapped the legend template with GestureDetector. We change the seriesVisibility list in its onTap callback based on the tapped series index value and then assign the empty data source value to the corresponding series, which has the series visibility set to false as shown in the code snippet below.

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  late List<ChartDataView> _chartData;
  final List<bool> _seriesVisibility = [true, false, false, false, false];
  @override
  void initState() {
    _chartData = [
      ChartDataView(
        period: DateTime(2000),
        loadConsumption: 40,
        exportFromGrid: 90,
        solar: 50,
        importFromGrid: 10,
        selfConsumption: 70,
      ),
      ChartDataView(
        period: DateTime(2001),
        loadConsumption: 20,
        exportFromGrid: 30,
        solar: 60,
        importFromGrid: 30,
        selfConsumption: 80,
      ),
      ChartDataView(
        period: DateTime(2002),
        loadConsumption: 70,
        exportFromGrid: 40,
        solar: 80,
        importFromGrid: 40,
        selfConsumption: 30,
      ),
      ChartDataView(
        period: DateTime(2003),
        loadConsumption: 80,
        exportFromGrid: 10,
        solar: 20,
        importFromGrid: 30,
        selfConsumption: 40,
      ),
      ChartDataView(
        period: DateTime(2004),
        loadConsumption: 60,
        exportFromGrid: 40,
        solar: 30,
        importFromGrid: 20,
        selfConsumption: 10,
      ),
      ChartDataView(
        period: DateTime(2005),
        loadConsumption: 50,
        exportFromGrid: 70,
        solar: 60,
        importFromGrid: 50,
        selfConsumption: 40,
      ),
      ChartDataView(
        period: DateTime(2006),
        loadConsumption: 70,
        exportFromGrid: 60,
        solar: 90,
        importFromGrid: 80,
        selfConsumption: 20,
      ),
      ChartDataView(
        period: DateTime(2007),
        loadConsumption: 90,
        exportFromGrid: 80,
        solar: 30,
        importFromGrid: 50,
        selfConsumption: 10,
      ),
      ChartDataView(
        period: DateTime(2008),
        loadConsumption: 30,
        exportFromGrid: 20,
        solar: 60,
        importFromGrid: 40,
        selfConsumption: 60,
      ),
      ChartDataView(
        period: DateTime(2009),
        loadConsumption: 50,
        exportFromGrid: 60,
        solar: 70,
        importFromGrid: 80,
        selfConsumption: 30,
      ),
      ChartDataView(
        period: DateTime(2010),
        loadConsumption: 10,
        exportFromGrid: 80,
        solar: 90,
        importFromGrid: 70,
        selfConsumption: 90,
      ),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SfCartesianChart(
          primaryXAxis: DateTimeAxis(),
          primaryYAxis: NumericAxis(),
          legend: Legend(
            isVisible: true,
            position: LegendPosition.top,
            overflowMode: LegendItemOverflowMode.wrap,
            legendItemBuilder: (String legendText, dynamic series,
                dynamic point, int seriesIndex) {
              debugPrint('seriesIndex => $seriesIndex');
              debugPrint('legendText => $legendText');
              return Padding(
                padding: const EdgeInsets.all(10),
                child: GestureDetector(
                  onTap: () {
                    setState(() {
                      _seriesVisibility[seriesIndex] =
                          !_seriesVisibility[seriesIndex];
                    });
                  },
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Icon(
                        Icons.circle,
                        color: seriesIndex == 0
                            ? Colors.amber
                            : seriesIndex == 1
                                ? Colors.red
                                : seriesIndex == 2
                                    ? Colors.green
                                    : seriesIndex == 3
                                        ? Colors.yellowAccent
                                        : Colors.blue,
                        size: 10,
                      ),
                      const SizedBox(width: 10),
                      Text(
                        series.name!,
                        style: TextStyle(
                          fontSize: 12,
                          color: _seriesVisibility[seriesIndex]
                              ? Colors.black
                              : Colors.grey.shade600,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
          series: <CartesianSeries<ChartDataView, DateTime>>[
            SplineAreaSeries<ChartDataView, DateTime>(
              dataSource: _seriesVisibility[0] ? _chartData : <ChartDataView>[],
              isVisible: _seriesVisibility[0],
              name: 'Load Consumption',
              xValueMapper: (ChartDataView data, _) => data.period,
              yValueMapper: (ChartDataView data, _) => data.loadConsumption,
              color: Colors.amber,
            ),
            SplineAreaSeries<ChartDataView, DateTime>(
              dataSource: _seriesVisibility[1] ? _chartData : <ChartDataView>[],
              isVisible: _seriesVisibility[1],
              name: 'Export to Grid',
              xValueMapper: (ChartDataView data, _) => data.period,
              yValueMapper: (ChartDataView data, _) => data.exportFromGrid,
              color: Colors.red,
            ),
            SplineAreaSeries<ChartDataView, DateTime>(
              dataSource: _seriesVisibility[2] ? _chartData : <ChartDataView>[],
              isVisible: _seriesVisibility[2],
              name: 'Solar',
              xValueMapper: (ChartDataView data, _) => data.period,
              yValueMapper: (ChartDataView data, _) => data.solar,
              color: Colors.green,
            ),
            SplineAreaSeries<ChartDataView, DateTime>(
              dataSource: _seriesVisibility[3] ? _chartData : <ChartDataView>[],
              isVisible: _seriesVisibility[3],
              name: 'Import from Grid',
              xValueMapper: (ChartDataView data, _) => data.period,
              yValueMapper: (ChartDataView data, _) => data.importFromGrid,
              color: Colors.yellowAccent,
            ),
            SplineAreaSeries<ChartDataView, DateTime>(
              dataSource: _seriesVisibility[4] ? _chartData : <ChartDataView>[],
              isVisible: _seriesVisibility[4],
              name: 'Self Consumption',
              xValueMapper: (ChartDataView data, _) => data.period,
              yValueMapper: (ChartDataView data, _) => data.selfConsumption,
              color: Colors.blue,
            ),
          ],
        ),
      ),
    );
  }
}

class ChartDataView {
  final DateTime period;
  final num loadConsumption;
  final num exportFromGrid;
  final num solar;
  final num importFromGrid;
  final num selfConsumption;

  ChartDataView({
    required this.period,
    required this.loadConsumption,
    required this.exportFromGrid,
    required this.solar,
    required this.importFromGrid,
    required this.selfConsumption,
  });
}

Note: However, your UI appearance is the same as the default legend appearance. Default legend will work for your scenario without any issues. Hence, we also suggest using the default legend instead of the legendItemBuilder, and for the legend icon, you can use the legendIconType property in the series and set the required shape based on your requirement.

Also attached the sample and recording below for your reference and you can modify the sample according to your needs. If you have further queries, please get back to us.

Regards, Hari Hara Sudhan. K. 506132.zip _506132.zip

azizainunnajib commented 12 months ago

Hi @sfHariHaraSudhan thanks fo rthe reply and the solution it woks so well. but there's little problem, if i give the tooltip, sometime the tooltip and legend is not working. but i solve it with tooltip builder. even the arrow of tolltips is not perfect. but hope it's fine.

this is the not perfect (in tooltip) I mention earlier. Screenshot_20231004-053402