Empty points in React Accumulation chart component
4 Sep 202524 minutes to read
The data points those uses the null
or undefined
as value are considered as empty points. The empty data points are ignored and not plotted in the chart. You can customize those points, using the emptyPointSettings
property in series. The default mode of the empty point is Gap
. Other supported modes are Average
and Zero
.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective, AccumulationDataLabel, Inject } from '@syncfusion/ej2-react-charts';
function App() {
const data = [
{ x: 'Jan', y: null, text: 'Jan: 3' }, { x: 'Feb', y: 3.5, text: 'Feb: 3.5' },
{ x: 'Mar', y: 7, text: 'Mar: 7' }, { x: 'Apr', y: 13.5, text: 'Apr: 13.5' },
{ x: 'May', y: 19, text: 'May: 19' }, { x: 'Jun', y: undefined, text: 'Jun: 23.5' },
{ x: 'Jul', y: 26, text: 'Jul: 26' }, { x: 'Aug', y: 25, text: 'Aug: 25' },
{ x: 'Sep', y: 21, text: 'Sep: 21' }, { x: 'Oct', y: 15, text: 'Oct: 15' }
];
const datalabel = { visible: true };
const emptypointsettings = { mode: 'Zero', fill: 'pink' };
return <AccumulationChartComponent id='charts'>
<Inject services={[AccumulationDataLabel]}/>
<AccumulationSeriesCollectionDirective>
<AccumulationSeriesDirective dataSource={data} xName='x' yName='y' dataLabel={datalabel} emptyPointSettings={emptypointsettings}>
</AccumulationSeriesDirective>
</AccumulationSeriesCollectionDirective>
</AccumulationChartComponent>;
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective,
AccumulationDataLabel, Inject,AccumulationDataLabelSettingsModel} from'@syncfusion/ej2-react-charts';
function App() {
const data: any[] = [
{ x: 'Jan', y: null, text: 'Jan: 3' }, { x: 'Feb', y: 3.5, text: 'Feb: 3.5' },
{ x: 'Mar', y: 7, text: 'Mar: 7' }, { x: 'Apr', y: 13.5, text: 'Apr: 13.5' },
{ x: 'May', y: 19, text: 'May: 19' }, { x: 'Jun', y: undefined, text: 'Jun: 23.5' },
{ x: 'Jul', y: 26, text: 'Jul: 26' }, { x: 'Aug', y: 25, text: 'Aug: 25' },
{ x: 'Sep', y: 21, text: 'Sep: 21' }, { x: 'Oct', y: 15, text: 'Oct: 15' }];
const datalabel: AccumulationDataLabelSettingsModel = { visible: true };
const emptypointsettings: EmptyPointSettingsModel = { mode: 'Zero', fill: 'pink' };
return <AccumulationChartComponent id='charts'>
<Inject services={[AccumulationDataLabel]} />
<AccumulationSeriesCollectionDirective>
<AccumulationSeriesDirective dataSource={data} xName='x' yName='y' dataLabel={datalabel} emptyPointSettings={emptypointsettings} >
</AccumulationSeriesDirective>
</AccumulationSeriesCollectionDirective>
</AccumulationChartComponent>
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
Customization
Specific color for an empty point can be set by using the fill
property in emptyPointSettings
and the border for an empty point can be set by using the border
property.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective, Inject, AccumulationDataLabel } from '@syncfusion/ej2-react-charts';
function App() {
const data = [
{ x: 'Jan', y: null, text: 'Jan: 3' }, { x: 'Feb', y: 3.5, text: 'Feb: 3.5' },
{ x: 'Mar', y: 7, text: 'Mar: 7' }, { x: 'Apr', y: 13.5, text: 'Apr: 13.5' },
{ x: 'May', y: 19, text: 'May: 19' }, { x: 'Jun', y: undefined, text: 'Jun: 23.5' },
{ x: 'Jul', y: 26, text: 'Jul: 26' }, { x: 'Aug', y: 25, text: 'Aug: 25' },
{ x: 'Sep', y: 21, text: 'Sep: 21' }, { x: 'Oct', y: 15, text: 'Oct: 15' }
];
const datalabel = { visible: true };
const emptypointsettings = { mode: 'Average', fill: 'black' };
return <AccumulationChartComponent id='charts'>
<Inject services={[AccumulationDataLabel]}/>
<AccumulationSeriesCollectionDirective>
<AccumulationSeriesDirective dataSource={data} xName='x' yName='y' emptyPointSettings={emptypointsettings} dataLabel={datalabel}>
</AccumulationSeriesDirective>
</AccumulationSeriesCollectionDirective>
</AccumulationChartComponent>;
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective,
Inject, AccumulationDataLabel,EmptyPointSettingsModel,AccumulationDataLabelSettingsModel} from'@syncfusion/ej2-react-charts';
function App() {
const data: any[] = [
{ x: 'Jan', y: null, text: 'Jan: 3' }, { x: 'Feb', y: 3.5, text: 'Feb: 3.5' },
{ x: 'Mar', y: 7, text: 'Mar: 7' }, { x: 'Apr', y: 13.5, text: 'Apr: 13.5' },
{ x: 'May', y: 19, text: 'May: 19' }, { x: 'Jun', y: undefined, text: 'Jun: 23.5' },
{ x: 'Jul', y: 26, text: 'Jul: 26' }, { x: 'Aug', y: 25, text: 'Aug: 25' },
{ x: 'Sep', y: 21, text: 'Sep: 21' }, { x: 'Oct', y: 15, text: 'Oct: 15' }];
const datalabel: AccumulationDataLabelSettingsModel = { visible: true };
const emptypointsettings: EmptyPointSettingsModel = { mode: 'Average', fill: 'black' }
return <AccumulationChartComponent id='charts'>
<Inject services={[AccumulationDataLabel]} />
<AccumulationSeriesCollectionDirective>
<AccumulationSeriesDirective dataSource={data} xName='x' yName='y'
emptyPointSettings={emptypointsettings} dataLabel={datalabel}>
</AccumulationSeriesDirective>
</AccumulationSeriesCollectionDirective>
</AccumulationChartComponent>
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
Handling No Data
When no data is available to render in the accumulation chart, the noDataTemplate
property can be used to display a custom layout within the chart area. This layout may include a message indicating the absence of data, a relevant image, or a button to initiate data loading. Styled text, images, or interactive elements can be incorporated to maintain design consistency and improve user guidance. Once data becomes available, the chart automatically updates to display the appropriate visualization.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective, PieSeries, Inject } from '@syncfusion/ej2-react-charts';
import { accData } from '../datasource.ts';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [hasData, setHasData] = React.useState(false);
var chart;
React.useEffect(() => {
if (hasData) {
const buttonContainer = document.getElementById("syncfusionButtonContainer");
if (buttonContainer) {
ReactDOM.unmountComponentAtNode(buttonContainer);
}
}
}, [hasData]);
const SAMPLE_CSS = `
#noDataTemplateContainer {
height: inherit;
width: inherit;
}
.light-bg {
background-color: #fafafa;
color: #000000;
}
.template-align img {
max-width: 150px;
/* Adjust size as needed */
max-height: 150px;
margin-top: 55px;
}
.load-data-btn {
border-radius: 4px;
}
.template-align {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
flex-direction: column;
}
#syncfusionButtonContainer {
margin-top: 5px;
}`;
const noDataTemplate = `
<div id="noDataTemplateContainer" class="light-bg">
<div class="template-align">
<img src="no-data.png" alt="No Data"/>
</div>
<div class="template-align">
<p style="font-size: 15px; margin: 10px 0 10px;"><strong>No data available to display.</strong></p>
</div>
<div class="template-align">
<div id="syncfusionButtonContainer"></div>
</div>
</div>
`;
// Function to load data when button is clicked
const loadData = () => {
if (chart) {
chart.series[0].dataSource = accData;
}
};
// Function to load data when button is clicked
const loadedChartData = () => {
if (!hasData) {
const buttonContainer = document.getElementById("syncfusionButtonContainer");
if (buttonContainer && !buttonContainer.hasChildNodes()) {
// Create the button element using React.createElement
const buttonElement = React.createElement(ButtonComponent, {
id: "loadDataButton",
content: "Load Data",
iconCss: "e-icons e-refresh",
cssClass: "load-data-btn e-outline",
isPrimary: false,
onClick: loadData
});
const root = createRoot(buttonContainer);
root.render(buttonElement);
}
}
};
return (
<div>
{/* Custom No Data Template with Button */}
<style>{SAMPLE_CSS}</style>
{/* Chart Component */}
<div id="chart-container"><AccumulationChartComponent id='charts' ref={g => chart = g} loaded={loadedChartData} noDataTemplate={noDataTemplate}>
<Inject services={[PieSeries]} />
<AccumulationSeriesCollectionDirective>
<AccumulationSeriesDirective xName='x' yName='y' type='Pie'>
</AccumulationSeriesDirective>
</AccumulationSeriesCollectionDirective>
</AccumulationChartComponent>
</div>
</div>
);
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { createRoot } from 'react-dom/client';
import { useEffect, useRef, useState } from 'react';
import { AccumulationChartComponent, AccumulationSeriesCollectionDirective, AccumulationSeriesDirective, PieSeries, Inject } from '@syncfusion/ej2-react-charts';
import { accData } from 'datasource.ts';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
var chart: AccumulationChartComponent | null;
const [hasData, setHasData] = React.useState(false);
React.useEffect(() => {
if (hasData) {
const buttonContainer = document.getElementById("syncfusionButtonContainer");
if (buttonContainer) {
ReactDOM.unmountComponentAtNode(buttonContainer);
}
}
}, [hasData]);
const SAMPLE_CSS = `
#noDataTemplateContainer {
height: inherit;
width: inherit;
}
.light-bg {
background-color: #fafafa;
color: #000000;
}
.template-align img {
max-width: 150px;
/* Adjust size as needed */
max-height: 150px;
margin-top: 55px;
}
.load-data-btn {
border-radius: 4px;
}
.template-align {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
flex-direction: column;
}
#syncfusionButtonContainer {
margin-top: 5px;
}`;
const noDataTemplate = `
<div id="noDataTemplateContainer" class="light-bg">
<div class="template-align">
<img src="no-data.png" alt="No Data"/>
</div>
<div class="template-align">
<p style="font-size: 15px; margin: 10px 0 10px;"><strong>No data available to display.</strong></p>
</div>
<div class="template-align">
<div id="syncfusionButtonContainer"></div>
</div>
</div>
`;
// Function to load data when button is clicked
const loadData = () => {
if (chart) {
(chart as AccumulationChartComponent).series[0].dataSource = accData;
}
};
// Function to load data when button is clicked
const loadedChartData = () => {
if (!hasData) {
const buttonContainer = document.getElementById("syncfusionButtonContainer");
if (buttonContainer && !buttonContainer.hasChildNodes()) {
// Create the button element using React.createElement
const buttonElement = React.createElement(ButtonComponent, {
id: "loadDataButton",
content: "Load Data",
iconCss: "e-icons e-refresh",
cssClass: "load-data-btn e-outline",
isPrimary: false,
onClick: loadData
});
const root = createRoot(buttonContainer);
root.render(buttonElement);
}
}
};
return (
<div>
{/* Custom No Data Template with Button */}
<style>{SAMPLE_CSS}</style>
{/* Chart Component */}
<div id="chart-container"><AccumulationChartComponent id='charts' ref={g => chart = g} loaded={loadedChartData} noDataTemplate={noDataTemplate} >
<Inject services={[PieSeries]} />
<AccumulationSeriesCollectionDirective>
<AccumulationSeriesDirective xName='x' yName='y' type='Pie'>
</AccumulationSeriesDirective>
</AccumulationSeriesCollectionDirective>
</AccumulationChartComponent>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));