Articles in this section
Category / Section

How to Manage Dynamic Series and Color with Riverpod in Flutter Chart?

7 mins read

Introduction

In this article, we will demonstrate how to use Riverpod for state management in SyncfusionFlutter Chart. Riverpod is a powerful and flexible state management library for Flutter, and when combined with Syncfusion® rich charting capabilities, it can provide an efficient way to manage the state of chart series and chart properties. Specifically, this article will explain how to maintain and change the state of the selected chart type (Line Series or Column Series) and the color of the line series using Riverpod . By the end of this guide, you will understand how to integrate Riverpod into a Flutter app with Syncfusion® charts, ensuring that the chart updates based on user interactions while maintaining its state across different components.

Setting Up Riverpod and Syncfusion® Flutter Charts

Before we dive into the code, let’s first set up the required packages for Riverpod and Syncfusion Flutter Charts in your Flutter project.

1. Add Dependencies

In your pubspec.yaml file, include the following dependencies:

dependencies:
 flutter:
   sdk: flutter
 syncfusion_flutter_charts: ^28.2.5+1
 flutter_riverpod: ^2.6.1 

Run flutter pub get to install these dependencies.

2. Import Required Packages

Import the necessary packages in your Dart file:

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:syncfusion_flutter_charts/charts.dart'; 

State Management with Riverpod

In this section, we’ll explain how to use Riverpod’s state management to control the chart’s series type and color dynamically.

1. Enum for Chart Series Type

We define an enum called ChartSeriesType to manage the types of chart series that the user can choose from. In this example, we are allowing two types: line and column.

enum ChartSeriesType { line, column } 

2.State Notifiers

StateNotifier is used to manage the mutable state in Riverpod . We will create two state notifiers:

  • One for the chart series type (ChartSeriesNotifier).
  • One for the line color (LineColorNotifier).

ChartSeriesNotifier
The ChartSeriesNotifier manages the state of the selected chart series type. By default, the chart will use the line series type.

class ChartSeriesNotifier extends StateNotifier<ChartSeriesType> {
 ChartSeriesNotifier() : super(ChartSeriesType.line);

 void updateSeries(ChartSeriesType newSeries) {
   state = newSeries;
 }
} 
  • Constructor: The ChartSeriesNotifier constructor initializes the state to ChartSeriesType.line, meaning that when the app starts, the default chart type will be a line chart.
  • updateSeries(): This method allows us to update the chart series type when the user selects a new series type.

LineColorNotifier

The LineColorNotifier manages the state of the line color. Initially, the line color is set to blue.

class LineColorNotifier extends StateNotifier<Color> {
 LineColorNotifier() : super(Colors.blue); // Default color

 void updateColor(Color newColor) {
   state = newColor;
 }
} 
  • Constructor: The constructor initializes the line color to Colors.blue.
  • updateColor(): This method updates the line color based on the user’s selection.

3. Defining Providers

Providers are used to expose the state to the widget tree. We create two providers:

  • chartSeriesProvider: Provides the current chart series type.
  • lineColorProvider: Provides the current color for the line series.
final chartSeriesProvider =
   StateNotifierProvider<ChartSeriesNotifier, ChartSeriesType>(
 (ref) => ChartSeriesNotifier(),
);

final lineColorProvider = StateNotifierProvider<LineColorNotifier, Color>(
   (ref) => LineColorNotifier()); 
  • StateNotifierProvider: This type of provider is used to expose a StateNotifier to the widget tree. The chartSeriesProvider and lineColorProvider allow other widgets to read and modify their states.
  • Building the User Interface
    Now, let’s walk through the widget code where we use the state managed by Riverpod to dynamically update the chart and its properties.

Main Application Widget
We start by wrapping the root widget with ProviderScope to ensure that Riverpod’s state management works correctly. ProviderScope is the root container that stores and manages all Riverpod providers, ensuring their state is accessible throughout the app. It enables efficient state management, handles provider lifecycles, and prevents memory leaks.

void main() {
 runApp(
   ProviderScope(
     child: MyApp(),
   ),
 );
} 

ProviderScope: This widget is the root of the app that enables Riverpod to work with the entire widget tree.

Class Overview:
The ChartScreen widget extends ConsumerWidget, which means it uses Riverpod’s WidgetRef to consume providers (state) and automatically rebuild the widget when the state changes. This widget allows the user to:

Choose between different chart series types.

  • Update the chart’s data dynamically.
  • Change the line color using buttons.

State Management with Riverpod:

  • chartSeriesProvider: This provider manages the selected chart series type (e.g., Line, Column).
  • lineColorProvider: This provider manages the color of the line in the chart.

How ref.watch() works:

ref.watch() is used to “listen” to the state of a provider. This means whenever the provider’s state changes, the widget that called ref.watch() will rebuild. In this case, we watch the state of the chartSeriesProvider and the lineColorProvider.

final selectedSeries = ref.watch(chartSeriesProvider);  // Watches the selected chart series type
final lineColor = ref.watch(lineColorProvider);  // Watches the line color 

These lines ensure that any time the state of these providers changes, the widget will rebuild, and the chart will reflect the changes accordingly.

Setting Up the Dropdown for Series Type:
A DropdownButton is used to allow the user to choose between different chart series types. Here’s how it works:

DropdownButton<ChartSeriesType>(
 value: selectedSeries,  // This binds to the current selected series from the provider
 onChanged: (ChartSeriesType? newValue) {
   if (newValue != null) {
     ref.read(chartSeriesProvider.notifier).updateSeries(newValue);  // Updates the series type provider when the user selects a new series type
   }
 },
 items: ChartSeriesType.values.map((ChartSeriesType series) {
   return DropdownMenuItem<ChartSeriesType>(
     value: series,
     child: Text(series.toString().split('.').last.toUpperCase()),  // Display the enum values in a user-friendly format
   );
 }).toList(),
), 
  • value: selectedSeries: The current selected series type is passed to the dropdown, which means the dropdown will display the selected series when the user opens it.
  • onChanged:: When the user selects a new series type, the onChanged function is triggered. This updates the state of chartSeriesProvider using ref.read(chartSeriesProvider.notifier).updateSeries(newValue). Essentially, this updates the chart series type to the selected value.
  • items: We use ChartSeriesType.values.map() to generate the dropdown items dynamically from the enum ChartSeriesType. Each item in the dropdown represents a series type.

Setting Up the Chart Display:
We use the SfCartesianChart widget from the Syncfusion® package to display the chart. The chart updates based on the selected series type and color.

Expanded(
 child: SfCartesianChart(
   primaryXAxis: CategoryAxis(),  // Sets the X-axis to be a category axis
   series: _getChartSeries(selectedSeries, lineColor),  // Gets the chart series based on selected series type and line color
 ),
), 

primaryXAxis: CategoryAxis(): Sets the X-axis as a category axis (ideal for categorical data like months).
series: _getChartSeries(selectedSeries, lineColor): The series for the chart is generated by the _getChartSeries function based on the selected chart series type and the selected line color. We will explain this function in more detail shortly.

Setting the Chart Data:
The _getChartSeries function is responsible for returning the correct series based on the selected series type.

List<CartesianSeries<dynamic, String>> _getChartSeries(ChartSeriesType seriesType, Color lineColor) {
 final chartData = [
   _ChartData('Jan', 30),
   _ChartData('Feb', 40),
   _ChartData('Mar', 35),
   _ChartData('Apr', 50),
   _ChartData('May', 45),
 ];

 switch (seriesType) {
   case ChartSeriesType.line:
     return [
       LineSeries<_ChartData, String>(
         dataSource: chartData,  // Passes the chart data to the line series
         xValueMapper: (data, _) => data.month,  // Maps the X-axis to the month
         yValueMapper: (data, _) => data.value,  // Maps the Y-axis to the value
         color: lineColor,  // Sets the line color based on the provider's state
       ),
     ];
   case ChartSeriesType.column:
     return [
       ColumnSeries<_ChartData, String>(
         dataSource: chartData,  // Passes the chart data to the column series
         xValueMapper: (data, _) => data.month,  // Maps the X-axis to the month
         yValueMapper: (data, _) => data.value,  // Maps the Y-axis to the value
       ),
     ];
 }
} 
  • chartData: The chart data consists of a list of _ChartData objects, where each object represents a month and its corresponding value.
  • switch (seriesType): Based on the seriesType (line or column), the appropriate series (LineSeries or ColumnSeries) is returned.
  • LineSeries: For the line series, we provide the dataSource as chartData, and we map the X-axis and Y-axis to the month and value, respectively. We also pass the lineColor which is obtained from the provider.
  • ColumnSeries: Similar to the line series, but it creates a column chart instead.

Updating Line Color:
If the selected series is a line chart, the color can be updated using a set of buttons. Each button is linked to a specific color, and when clicked, the color changes the line color in the chart.

Widget _buildColorButtons(WidgetRef ref) {
 return Row(
   mainAxisAlignment: MainAxisAlignment.center,
   children: [
     _colorButton(ref, Colors.red, 'Red'),
     _colorButton(ref, Colors.green, 'Green'),
     _colorButton(ref, Colors.blue, 'Blue'),
   ],
 );
} 
  • The Row widget holds multiple color buttons.
  • Each button is created using the _colorButton helper method.

Helper Method to Create Color Buttons:
The _colorButton method creates a button that updates the line color when pressed.

Widget _colorButton(WidgetRef ref, Color color, String label) {
 return ElevatedButton(
   onPressed: () => ref.read(lineColorProvider.notifier).updateColor(color),
   child: Text(label),
 );
} 

onPressed: When a button is pressed, the ref.read(lineColorProvider.notifier).updateColor(color) method is called, which updates the color of the line series.
label: The label of the button (Red, Green, Blue) is passed to display on the button.

Conclusion:
This example demonstrates how Riverpod is used to manage state in Flutter applications:

Providers: (chartSeriesProvider and lineColorProvider) are used to store and manage the chart’s series type and line color.
ref.watch() is used to rebuild the widget when the state of the providers changes.
The Dropdown allows users to select the series type, and buttons allow users to change the line color dynamically.
The SfCartesianChart widget from Syncfusion® is used to display the selected series and color.
By using Riverpod for state management, we can keep the widget tree clean, and the chart’s state can be updated in response to user interactions (like changing the series type or line color).

Demo:

StateManagementUsingReiverpod-ezgifcom-video-to-gif-converter.gif

Conclusion

I hope you enjoyed learning about how to manage dynamic series and color with riverpod in Flutter Chart.

You can refer to our Flutter CartesianChart feature tour page to know about its other groundbreaking feature representations.
You can also explore our
Flutter CartesianChart documentation to understand how to create and manipulate data.

For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.

If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our
support forums, Direct-Trac, or feedback portal. We are always happy to assist you!

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied