Syncfusion AI Assistant

How can I help you?

Dynamic data update in EJ2 TypeScript Chart control

3 Feb 202623 minutes to read

The EJ2 TypeScript Chart control provides methods to dynamically modify data without requiring a full chart refresh. This enables real-time data visualization, interactive features, and responsive user experiences. Common scenarios include adding sensor readings, removing outdated data points, replacing entire datasets, and enabling click-based data manipulation.

Adding a new data point

Use the addPoint method to dynamically append a new data point to a series. This is useful for real-time data streams, user interactions, or incremental data loading. The method accepts the following parameters:

  • Data point (required): The new data object to append to the series (must match the datasource structure)
  • Animation duration (optional): Duration in milliseconds for the entry animation
import { Chart, SplineSeries, Category, DataLabel, Legend } from '@syncfusion/ej2-charts';
Chart.Inject(SplineSeries, Category, DataLabel, Legend);

let addData: Object[] = [
    { x: "Germany", y: 72 },
    { x: "Russia", y: 103.1 },
    { x: "Brazil", y: 139.1 },
    { x: "India", y: 462.1 },
    { x: "China", y: 721.4 },
    { x: "USA", y: 286.9 },
    { x: "Great Britain", y: 115.1 },
    { x: "Nigeria", y: 97.2 }
];

let chart: Chart = new Chart({
    primaryXAxis: {
        valueType: 'Category', enableTrim: false, majorTickLines: { width: 0 }, majorGridLines: { width: 0 }
    },
    chartArea: { border: { width: 1 } },
    primaryYAxis:
    {
        minimum: 0, maximum: 800, labelFormat: '{value}M', edgeLabelPlacement: 'Shift'
    },
    series: [
        {
            dataSource: addData, xName: 'x', yName: 'y', type: 'Spline', width: 2, name: 'Users',
            marker: { visible: true, dataLabel: { visible: true, position: 'Top', font: { fontWeight: '600' } } }
        }
    ],
    title: 'Internet Users - 2016',
    legendSettings: {
        visible: false
    }
}, '#element');

document.getElementById('add').onclick = function () {
    chart.series[0].addPoint({ x: 'Japan', y: 118.2 });
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Animation</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
        <button id='add'>Add Point</button>
    </div>
</body>

</html>

Removing an existing data point

Use the removePoint method to dynamically delete a data point from a series by its index. This is useful for filtering data, removing outliers, or responding to user actions. The method accepts the following parameters:

  • Point index (required): The zero-based index of the data point to remove
  • Animation duration (optional): Duration in milliseconds for the exit animation
import { Chart, SplineSeries, Category, DataLabel, Legend } from '@syncfusion/ej2-charts';
Chart.Inject(SplineSeries, Category, DataLabel, Legend);

let removeData: Object[] = [
    { x: "Germany", y: 72 },
    { x: "Russia", y: 103.1 },
    { x: "Brazil", y: 139.1 },
    { x: "India", y: 462.1 },
    { x: "China", y: 721.4 },
    { x: "USA", y: 286.9 },
    { x: "Great Britain", y: 115.1 },
    { x: "Nigeria", y: 97.2 }
];

let chart: Chart = new Chart({
    primaryXAxis: {
        valueType: 'Category', enableTrim: false, majorTickLines: { width: 0 }, majorGridLines: { width: 0 }
    },
    chartArea: { border: { width: 1 } },
    primaryYAxis:
    {
        minimum: 0, maximum: 800, labelFormat: '{value}M', edgeLabelPlacement: 'Shift'
    },
    series: [
        {
            dataSource: removeData, xName: 'x', yName: 'y', type: 'Spline', width: 2, name: 'Users',
            marker: { visible: true, dataLabel: { visible: true, position: 'Top', font: { fontWeight: '600' } } }
        }
    ],
    title: 'Internet Users - 2016',
    legendSettings: {
        visible: false
    }
}, '#element');

document.getElementById('remove').onclick = function () {
    chart.series[0].removePoint(0);
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Animation</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
        <button id='remove'>Remove Point</button>
    </div>
</body>

</html>

Replacing entire data points

Use the setData method to replace all data points in a series with a new dataset. This is useful for category switching, time range changes, or complete data refreshes. The method accepts the following parameters:

  • New data source (required): The complete new dataset array to display
  • Animation duration (optional): Duration in milliseconds for the transition animation
import { Chart, ColumnSeries, Category, IAxisRangeCalculatedEventArgs } from '@syncfusion/ej2-charts';
Chart.Inject(ColumnSeries, Category);

let updatedData: Object[] = [
    { x: 'Jewellery', y: 75 },
    { x: 'Shoes', y: 45 },
    { x: 'Footwear', y: 73 },
    { x: 'Pet Services', y: 53 },
    { x: 'Business Clothing', y: 85 },
    { x: 'Office Supplies', y: 68 },
    { x: 'Food', y: 45 }
];

let chart: Chart = new Chart({
    primaryXAxis: {
        valueType: 'Category', majorGridLines: { width: 0 }, labelStyle: { size: '12px' }, labelIntersectAction: 'Rotate90'
    },
    chartArea: { border: { width: 0 } },
    primaryYAxis:
    {
        title: 'Sales (in percentage)', labelFormat: '{value}%', lineStyle: { width: 0 }, majorTickLines: { width: 0 }, interval: 5, minimum: 0, maximum: 100
    },
    series: [
        {
            dataSource: updatedData, xName: 'x', yName: 'y', type: 'Column',
            cornerRadius: { topLeft: 15, topRight: 15 }, columnWidth: 0.5
        }
    ],
    title: 'Sales by product',
    axisRangeCalculated: (args: IAxisRangeCalculatedEventArgs) => {
        if (args.axis.name === 'primaryYAxis') {
            args.maximum = args.maximum as number > 100 ? 100 : args.maximum;
            if (args.maximum > 80) {
                args.interval = 20;
            }
            else if (args.maximum > 40) {
                args.interval = 10;
            }
        }
    }
}, '#element');

function getRandomInt(min: number, max: number) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
document.getElementById('update').onclick = () => {
    const newData = updatedData.map((item: { x: string, y: number }) => {
        const value: number = getRandomInt(10, 90);
        return { x: item.x, y: value };
    });
    if (chart.series.length > 0) {
        chart.series[0].setData(newData, 500);
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Animation</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
        <button id='update'>Update Data</button>
    </div>
</body>

</html>

Click to add or remove a data point

Enable users to add or remove data points by clicking on the chart. Listen to the chartMouseClick event to capture click coordinates and point information. When a user clicks within the chart area, extract the x and y axis values from the event arguments. If the location is empty, use addPoint to add a new data point at those coordinates. If a user clicks on an existing data point, identify its index and use removePoint to delete it. This creates an intuitive interface for data exploration and editing.

import { Chart, LineSeries, DataLabel, Tooltip, IMouseEventArgs, IAxisRangeCalculatedEventArgs, Series } from '@syncfusion/ej2-charts';
Chart.Inject(LineSeries, DataLabel, Tooltip);

let chartData: Object[] = [
    { x: 20, y: 20 }, { x: 80, y: 80 }
];

let chart: Chart = new Chart({
    primaryXAxis: {
        edgeLabelPlacement: 'Shift', rangePadding: 'Additional', majorGridLines: { width: 0 }
    },
    chartArea: { border: { width: 0 } },
    primaryYAxis:
    {
        title: 'Value', interval: 20, lineStyle: { width: 0 }, majorTickLines: { width: 0 }
    },
    series: [
        {
            dataSource: chartData, xName: 'x', yName: 'y', type: 'Line', width: 3,
            marker: { visible: true, isFilled: true, border: { width: 2, color: 'White' }, width: 13, height: 13 }
        }
    ],
    title: 'User supplied data',
    tooltip: { enable: true },
    chartMouseClick: (args: IMouseEventArgs) => {
        let isRemoved: boolean = false;
        if (args.axisData) {
            for (let i: number = 0; i < (chart.series[0] as Series).points.length; i++) {
                let markerWidth: number = (chart.series[0] as Series).marker.width / 2;
                let roundedX: number = Math.round(args.axisData['primaryXAxis']) + markerWidth;
                let roundedY: number = Math.round(args.axisData['primaryYAxis']) + markerWidth;
                let pointX: number = Math.round((chart.series[0] as Series).points[i].x as number) + markerWidth;
                let pointY: number = Math.round((chart.series[0] as Series).points[i].y as number) + markerWidth;
                if ((roundedX === pointX || roundedX + 1 === pointX || roundedX - 1 === pointX) &&
                    (roundedY === pointY || roundedY + 1 === pointY || roundedY - 1 === pointY)) {
                    if ((chart.series[0] as Series).points.length > 1) {
                        const points = (chart.series[0] as Series).points;
                        const duration: number = i === 0 || i === points[points.length - 1].index ? 500 : 0;
                        chart.series[0].removePoint(i, duration);
                    }
                    isRemoved = true;
                }
            }
            if (!isRemoved) {
                chart.series[0].addPoint({x: Math.round(args.axisData['primaryXAxis']), y: Math.round(args.axisData['primaryYAxis'])});
            }
        }
    },
    axisRangeCalculated: (args: IAxisRangeCalculatedEventArgs)  => {
        if (args.axis.name === 'primaryXAxis') {
            if (args.interval < 10) {
                args.maximum = args.maximum + 10;
                args.minimum = args.minimum - 10;
                args.interval = 10;
            }
        }
        if (args.axis.name === 'primaryYAxis') {
            if (args.maximum <= 60) {
                args.interval = 10;
            }
        }
    }
}, '#addPoint');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Animation</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='addPoint'></div>
    </div>
</body>

</html>