Integrate Chart in Syncfusion Angular Grid
17 Sep 202524 minutes to read
The Grid and Chart Integration feature in Syncfusion enables users to visualize tabular data in graphical format by seamlessly linking the Grid with Chart components. This powerful feature allows interactive data visualization through various Chart types such as bar, line, or pie charts directly from Grid data using the ContextMenu functionality.
This integration is particularly valuable in dashboards, reporting tools, and data-driven applications where both tabular and visual representations enhance data comprehension and decision-making processes.
Steps for Chart Integration
Follow these comprehensive steps to integrate Charts into your Angular Grid:
Dependencies
The following dependencies are required for Chart integration functionality:
|-- dependencies
|-- @syncfusion/ej2-grid-chart
|--@syncfusion/ej2-angular-grids
|-- @syncfusion/ej2-base
|-- @syncfusion/ej2-buttons
|-- @syncfusion/ej2-dropdowns
|-- @syncfusion/ej2-grids
|-- @syncfusion/ej2-inputs
|-- @syncfusion/ej2-navigations
|-- @syncfusion/ej2-popups
|-- @syncfusion/ej2-splitbuttons
|-- @syncfusion/ej2-notifications
|-- @syncfusion/ej2-calendars
|-- @syncfusion/ej2-charts
Setup Angular Environment
Use Angular CLI to setup your Angular applications. Install Angular CLI using the following command:
npm install -g @angular/cli
Create an Angular Application
Start a new Angular application using the Angular CLI command:
ng new my-app
This command will prompt you for project settings such as Angular routing and stylesheet format preferences.
By default, it creates a CSS-based application.
Navigate to the created project folder:
cd my-app
Add Syncfusion Angular Packages
All Essential JS 2 packages are published in the npmjs.com registry.
Install the Grid-Chart
package using the following command:
npm install @syncfusion/ej2-grid-chart --save
Import Syncfusion CSS Styles
Syncfusion Angular controls include built-in themes available in installed packages. Apply themes by importing required CSS files from the node_modules directory.
To use the Material theme, add the following imports to the src/styles.css file:
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-notifications/styles/material.css';
@import '../node_modules/@syncfusion/ej2-angular-grids/styles/material.css';
@import '../node_modules/@syncfusion/ej2-grid-chart/styles/material.css';
Chart Integration via Context Menu in Grid
This section demonstrates how to dynamically render Charts based on user interactions within the Syncfusion Angular Grid using context menu functionality. Users can right-click on selected rows and choose from various Chart types to visualize data instantly, enhancing interactivity and providing seamless analytical experiences.
For example, in a sales dashboard, you can select sales records for specific products and instantly view comparative bar or pie Charts illustrating online versus retail sales or revenue trends over time. This functionality improves decision-making by providing immediate visual feedback.
Implementation Steps
Step 1: Inject Required Modules
Import necessary modules from Grid, Chart, and GridChart packages, and inject the ContextMenuService
to enable context menu functionality:
import { ContextMenuClickEventArgs, ContextMenuService, GridModule, ContextMenuItem, GridComponent} from '@syncfusion/ej2-angular-grids';
import { CategorySeries, ChartChanges, ChartPopupArgs, GridChart } from '@syncfusion/ej2-grid-chart';
import { ChartModel } from '@syncfusion/ej2-charts';
@Component({
imports: [ GridModule],
providers: [ContextMenuService],
standalone: true,
selector: 'app-root',
templateUrl: 'app.component.html',
})
Step 2: Define Chart Options in Grid Context Menu
Add Chart visualization options as context menu items using the contextMenuItems property:
export class AppComponent implements OnInit {
public contextMenuItems?: ContextMenuItem[];
ngOnInit(): void {
this.contextMenuItems = [ 'Bar', 'StackingBar', 'StackingBar100', 'Pie', 'Column', 'StackingColumn', 'StackingColumn100', 'Line', 'StackingLine', 'StackingLine100', 'Area', 'StackingArea', 'StackingArea100', 'Scatter'];
}
}
Step 3: Initialize GridChart Instance on Grid Creation
Inside the Grid’s created event, instantiate a GridChart object for dynamic Chart rendering:
created(): void {
this.gridChart = new GridChart({
enableRtl: (this.grid as GridComponent).enableRtl,
locale: (this.grid as GridComponent).locale,
});
}
This ensures Chart instance readiness for seamless context menu interaction.
Step 4: Handle Context Menu Click to Render Chart
Use the contextMenuClick event to detect selected Chart types and render Charts using the gridChart.render()
method.
The ContextMenuClick
event provides the following arguments:
-
args.chartType
: The selected Chart type -
args.gridInstance
: Current Grid instance -
args.records
: Selected data records for Chart visualization
Use gridChart.render
with three parameters:
-
chartArgs
: Contains Grid instance, Chart type, and selected records -
chartModel
: Specifies Chart configurations for appearance and behavior -
categorySeries
: Defines data fields for categories and series
contextMenuClick(args: ContextMenuClickEventArgs) {
if (args.chartType) {
// Prepare Chart arguments
const chartArgs: ChartPopupArgs = {
gridInstance: (args.gridInstance as GridComponent),
chartType: args.chartType,
records: args.records as SalesRecord[],
};
// Configure Chart model
const chartModel: ChartModel = {
primaryXAxis: {
valueType: 'Category',
labelRotation: 315
}
};
// Combine Chart models
const model: ChartChanges = { chart: chartModel, accumulationChart: {} };
// Define category and series fields
const categorySeries: CategorySeries = {
category: ['Product', 'Month'],
series: ['Online', 'Retail']
};
// Render Chart
(this.gridChart as GridChart).render(chartArgs, model, categorySeries);
}
}
The following complete example demonstrates Chart integration into Grid context menu:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { Component, OnInit, ViewChild } from '@angular/core';
import { ContextMenuClickEventArgs, ContextMenuService, GridModule, ContextMenuItem, GridComponent} from '@syncfusion/ej2-angular-grids';
import { CategorySeries, ChartChanges, ChartPopupArgs, GridChart } from '@syncfusion/ej2-grid-chart';
import { ChartModel } from '@syncfusion/ej2-charts';
import { salesDatas } from './datasource';
@Component({
imports: [ GridModule],
providers: [ContextMenuService],
standalone: true,
selector: 'app-root',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnInit {
@ViewChild('grid') public grid?: GridComponent;
public data?: Object[];
public gridChart?: GridChart;
public contextMenuItems?: ContextMenuItem[];
public selectionSettings?: Object;
ngOnInit(): void {
this.data = salesDatas;
this.selectionSettings = { type: 'Multiple' };
this.contextMenuItems= [ 'Bar', 'StackingBar', 'StackingBar100', 'Pie', 'Column', 'StackingColumn', 'StackingColumn100', 'Line', 'StackingLine', 'StackingLine100', 'Area', 'StackingArea', 'StackingArea100', 'Scatter'];
}
created(): void {
this.gridChart = new GridChart({
enableRtl: (this.grid as GridComponent).enableRtl,
locale: (this.grid as GridComponent).locale,
});
}
contextMenuClick(args: ContextMenuClickEventArgs) {
if (args.chartType) {
const chartArgs: ChartPopupArgs = {
gridInstance: (args.gridInstance as GridComponent),
chartType: args.chartType,
records: args.records as SalesRecord[],
};
const chartModel: ChartModel = {
primaryXAxis: {
valueType: 'Category',
labelRotation: 315
}
};
const model: ChartChanges = { chart: chartModel, accumulationChart: {} };
const categorySeries: CategorySeries = {
category: ['Product', 'Month'],
series: ['Online', 'Retail']
};
(this.gridChart as GridChart).render(chartArgs, model, categorySeries);
}
}
}
interface SalesRecord {
Product: string;
Category: string;
Year: number;
Online: number;
Retail: number;
ProfitLoss: number;
UnitsSold: number;
Revenue: number;
Image: string;
CategoryIcon: string;
}
<ejs-grid [dataSource]='data' #grid id="GridChart" height="500" allowSelection="true" [selectionSettings]='selectionSettings' [contextMenuItems]='contextMenuItems' (contextMenuClick)='contextMenuClick($event)' (created)='created()'>
<e-columns>
<e-column type='checkbox' width='50'></e-column>
<e-column field='Product' headerText='Product' width='200'></e-column>
<e-column field='Month' headerText='Month' width='140'></e-column>
<e-column field='Online' headerText='Online' format='C2' textAlign='Right' width='160'></e-column>
<e-column field='Total' headerText='Total' format='C2' textAlign='Right' width='160'></e-column>
</e-columns>
</ejs-grid>
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Enable Export Functionality in GridChart
Export functionality allows Charts to be saved in various formats for external sharing, reports, and presentations. This feature is particularly useful for preserving visualized data analysis.
Enable export by setting the allowExport
property to true when creating the GridChart instance:
gridChart = new GridChart({
allowExport: true
});
Once enabled, an export option appears in the Chart popup toolbar, supporting formats such as PDF, CSV, Print, JPEG, XLSX, SVG, and PNG.
Enable Property Panel in GridChart
The property panel provides a built-in interface for dynamic Chart modification at runtime. By default, this panel is disabled.
Enable the property panel by setting enablePropertyPanel
to true:
gridChart = new GridChart({
enablePropertyPanel: true
});
When enabled, the property panel appears alongside Chart popups and offers three main configuration sections:
Chart Types: Choose from various Chart types including Column, Line, Pie, and others.
Chart Data: Configure category axis and series fields for data visualization.
Formatting Options: Adjust styling properties including:
-
Chart Style:
- Margin: Adjust margins around Charts (top, bottom, left, right) for better layout spacing
- Color: Set distinct colors for different Chart elements to improve visual clarity
-
Title Style:
- Legend: Toggle legend visibility and customize font, size, color, and position
- Series: Enable/disable tooltips and customize Series colors and data labels based on categories
-
Axes: Select axes as category or value type, and customize:
- Reverse Order to change data sequence
- Title: Adjust text, font, size, color, and rotation
- Label: Modify text, font, size, color, and rotation for better presentation
Customize Chart Models
Customize Chart appearance by defining a chartModel object in the chart
property within the contextMenuClick event. Configure various Chart properties such as axes, margins, tooltips, titles, and more. Additionally, use Chart events within chartModel
configuration for further customization.
For Accumulation Charts (such as Pie charts), use the accumulationChart
property to configure titles, legends, data labels, and visual styles. Apply additional customizations using Accumulation Chart events.
The following code demonstrates Chart customization:
contextMenuClick(args: ContextMenuClickEventArgs) {
if (args.chartType) {
const chartArgs: ChartPopupArgs = {
gridInstance: (args.gridInstance as GridComponent),
chartType: args.chartType,
records: (args.records as SalesRecord[]),
};
const chartModel: ChartModel = {
primaryXAxis: {
valueType: 'Category',
labelRotation: 315,
},
margin: {
top: 20,
bottom: 20,
right: 20,
left: 20
},
tooltip: {
enable: true,
textStyle: {
size: '16px',
fontFamily: 'Arial, Helvetica, sans-serif'
}
},
title: 'Sales Data',
titleStyle: {
size: '24px',
fontFamily: 'Arial, Helvetica, sans-serif',
fontWeight: 'Bold'
},
subTitle: 'Sales data for various products over the months',
load: (args: ILoadedEventArgs) => {
if (args.chart.titleStyle) {
args.chart.titleStyle.color = '#1976d2';
}
}
};
const accumulationChartModel: AccumulationChartModel = {
title: 'Sales Distribution'
}
// Combine Chart models
const model: ChartChanges = {
chart: chartModel,
accumulationChart: accumulationChartModel
};
}
}
Programmatically update Chart appearance using the updateChartSettings
event provided by GridChart integration. This event triggers when modifying Chart properties through the Chart popup’s property panel, useful for applying custom themes, adjusting axis settings, or modifying series styles.
The following code demonstrates dynamic Chart customization with margin restrictions:
created(): void {
this.gridChart = new GridChart({
enablePropertyPanel: true,
allowExport: true,
enableRtl: (this.grid as GridComponent).enableRtl,
locale: (this.grid as GridComponent).locale,
updateChartSettings: this.updateChartSettings.bind(this),
});
}
updateChartSettings(args: UpdateChartArgs){
const chart = args.changes?.chart;
if (!chart) return;
// Restrict margin values to minimum 20
const chartMargin = chart.margin;
if (chartMargin && !isNullOrUndefined(chartMargin)) {
if ((chartMargin.top ?? 0) < 20) chartMargin.top = 20;
if ((chartMargin.bottom ?? 0) < 20) chartMargin.bottom = 20;
if ((chartMargin.left ?? 0) < 20) chartMargin.left = 20;
if ((chartMargin.right ?? 0) < 20) chartMargin.right = 20;
}
}
The following complete example demonstrates property panel enablement, Chart customization using chartModel
, and dynamic behavior control through updateChartSettings
:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { Component, OnInit, ViewChild } from '@angular/core';
import { ContextMenuClickEventArgs, ContextMenuService, GridModule, ContextMenuItem, GridComponent} from '@syncfusion/ej2-angular-grids';
import { CategorySeries, ChartChanges, ChartPopupArgs, GridChart, UpdateChartArgs } from '@syncfusion/ej2-grid-chart';
import { ChartModel, AccumulationChartModel, ILoadedEventArgs } from '@syncfusion/ej2-charts';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { salesDatas } from './datasource';
@Component({
imports: [ GridModule],
providers: [ContextMenuService],
standalone: true,
selector: 'app-root',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnInit {
@ViewChild('grid') public grid?: GridComponent;
public data?: Object[];
public gridChart?: GridChart;
public contextMenuItems?: ContextMenuItem[];
public selectionSettings?: Object;
ngOnInit(): void {
this.data = salesDatas;
this.selectionSettings = { type: 'Multiple' };
this.contextMenuItems= [ 'Bar', 'StackingBar', 'StackingBar100', 'Pie', 'Column', 'StackingColumn', 'StackingColumn100', 'Line', 'StackingLine', 'StackingLine100', 'Area', 'StackingArea', 'StackingArea100', 'Scatter'];
}
created(): void {
this.gridChart = new GridChart({
enablePropertyPanel: true,
allowExport: true,
enableRtl: (this.grid as GridComponent).enableRtl,
locale: (this.grid as GridComponent).locale,
updateChartSettings: this.updateChartSettings.bind(this),
});
}
contextMenuClick(args: ContextMenuClickEventArgs) {
if (args.chartType) {
const chartArgs: ChartPopupArgs = {
gridInstance: (args.gridInstance as GridComponent),
chartType: args.chartType,
records: (args.records as SalesRecord[]),
};
const chartModel: ChartModel = {
primaryXAxis: {
valueType: 'Category',
labelRotation: 315,
},
margin: {
top: 20,
bottom: 20,
right: 20,
left: 20
},
tooltip: {
enable: true,
textStyle: {
size: '16px',
fontFamily: 'Arial, Helvetica, sans-serif'
}
},
title: 'Sales Data',
titleStyle: {
size: '24px',
fontFamily: 'Arial, Helvetica, sans-serif',
fontWeight: 'Bold'
},
subTitle: 'Sales data for various products over the months',
load: (args: ILoadedEventArgs) => {
if (args.chart.titleStyle) {
args.chart.titleStyle.color = '#1976d2';
}
}
};
const accumulationChartModel: AccumulationChartModel = {
title :'Sales Distribution'
}
const model: ChartChanges = {
chart: chartModel,
accumulationChart: accumulationChartModel
};
const categorySeries: CategorySeries = {
category: ['Product', 'Month'],
series: ['Online', 'Retail']
};
(this.gridChart as GridChart).render(chartArgs, model, categorySeries);
}
}
updateChartSettings(args: UpdateChartArgs){
const chart = args.changes?.chart;
if (!chart) return;
const chartMargin = chart.margin;
if (chartMargin && !isNullOrUndefined(chartMargin)) {
if ((chartMargin.top ?? 0) < 20) chartMargin.top = 20;
if ((chartMargin.bottom ?? 0) < 20) chartMargin.bottom = 20;
if ((chartMargin.left ?? 0) < 20) chartMargin.left = 20;
if ((chartMargin.right ?? 0) < 20) chartMargin.right = 20;
}
}
}
interface SalesRecord {
Product: string;
Category: string;
Year: number;
Online: number;
Retail: number;
ProfitLoss: number;
UnitsSold: number;
Revenue: number;
Image: string;
CategoryIcon: string;
}
<ejs-grid [dataSource]='data' #grid id="GridChart" height="500" allowSelection="true" [selectionSettings]='selectionSettings' [contextMenuItems]='contextMenuItems' (contextMenuClick)='contextMenuClick($event)' (created)='created()'>
<e-columns>
<e-column type='checkbox' width='50'></e-column>
<e-column field='Product' headerText='Product' width='200'></e-column>
<e-column field='Month' headerText='Month' width='140'></e-column>
<e-column field='Online' headerText='Online' format='C2' textAlign='Right' width='160'></e-column>
<e-column field='Total' headerText='Total' format='C2' textAlign='Right' width='160'></e-column>
</e-columns>
</ejs-grid>
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));