How can I help you?
Working with data in EJ2 TypeScript Chart control
3 Feb 202624 minutes to read
The EJ2 TypeScript Chart control supports multiple data binding approaches to suit different application scenarios. Data can be bound from local JSON arrays, dynamically loaded on demand with lazy loading, or fetched from remote services using various adaptor patterns. This guide covers all available data binding methods, helping you choose the right approach for your use case based on data size, performance requirements, and backend architecture.
Choosing a data binding approach
| Method | Best For | Advantages | Considerations |
|---|---|---|---|
| Local data | Small to medium datasets | Simple setup, no network latency, instant rendering | All data must be in memory |
| Common datasource | Multiple series sharing data | Reduces redundancy, single update point | Limited to data common across series |
| Lazy loading | Large datasets with scrolling | Loads only visible data, better performance | Requires server-side pagination |
| Remote data (OData/WebAPI) | Backend-driven data | Scalable, centralized data management, real-time updates | Network latency, requires service setup |
| Offline mode | Data caching with client-side actions | Eliminates repeated requests, faster interactions | Initial load time, memory constraints |
Local data
Bind simple JSON data to the chart using the dataSource property in the series configuration. Map the JSON fields to the xName and yName properties to specify which data fields represent the x and y axis values.
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
Chart.Inject(ColumnSeries, Category);
let chartData: Object[] = [
{ month: 'Jan', sales: 35 }, { month: 'Feb', sales: 28 },
{ month: 'Mar', sales: 34 }, { month: 'Apr', sales: 32 },
{ month: 'May', sales: 40 }, { month: 'Jun', sales: 32 },
{ month: 'Jul', sales: 35 }, { month: 'Aug', sales: 55 },
{ month: 'Sep', sales: 38 }, { month: 'Oct', sales: 30 },
{ month: 'Nov', sales: 25 }, { month: 'Dec', sales: 32 }
];
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
series: [{
dataSource: chartData,
xName: 'month',
yName: 'sales',
type: 'Column'
}]
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Remote data
Bind remote data from a web service by using the DataManager class. The DataManager simplifies communication with REST APIs, OData services, and custom web endpoints. It requires minimal configuration—typically just the service URL and an appropriate adaptor—then handles all request/response processing. Assign the DataManager instance to the dataSource property in the series, and map the response fields to xName and yName. Use the optional query property to filter, sort, or paginate data on the server.
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
import { DataManager, Query } from '@syncfusion/ej2-data';
Chart.Inject(ColumnSeries, Category);
let dataManager: DataManager = new DataManager({
url: 'https://services.syncfusion.com/js/production/api/orders'
});
let query: Query = new Query().take(5).where('Estimate', 'lessThan', 3, false);
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
primaryYAxis:
{
title: 'Freight rate in U.S. dollars'
},
series: [
{
type: 'Column',
dataSource: dataManager,
xName: 'CustomerID', yName: 'Freight', query: query
}
],
title: 'Container freight rate'
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Binding data using ODataAdaptor
OData is a standardized protocol for creating and consuming data via REST APIs. Use the ODataAdaptor with DataManager to retrieve data from OData services. The adaptor automatically constructs the correct query syntax and handles standard OData conventions.
Example use case: Querying a product sales service that implements OData v3.0 filtering, sorting, and pagination.
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
import { DataManager, Query, ODataAdaptor } from '@syncfusion/ej2-data';
Chart.Inject(ColumnSeries, Category);
let dataManager: DataManager = new DataManager({
url: 'https://services.odata.org/V3/Northwind/Northwind.svc/Orders/',
adaptor: new ODataAdaptor(),
crossDomain: true
});
let query: Query = new Query();
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
//Initializing Chart Sample
series: [
{
type: 'Column',
dataSource: dataManager,
xName: 'CustomerID', yName: 'Freight', query: query
}
],
title: 'Sprint Task Analysis'
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Binding data using ODataV4Adaptor
ODataV4 is an improved and more standardized version of the OData protocol, with enhanced query capabilities and better JSON support. Use the ODataV4Adaptor to consume ODataV4 services. For more information on ODataV4 specifications, refer to the OData v4 documentation.
When to use ODataV4Adaptor: If your backend service implements OData v4.0, prefer this adaptor over the older ODataAdaptor for better compliance and features.
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
import { DataManager, Query, ODataV4Adaptor } from '@syncfusion/ej2-data';
Chart.Inject(ColumnSeries, Category);
let dataManager: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders',
adaptor: new ODataV4Adaptor()
});
let query: Query = new Query();
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
//Initializing Chart Sample
series: [
{
type: 'Column',
dataSource: dataManager,
xName: 'CustomerID', yName: 'Freight', query: query
}
],
title: 'Sprint Task Analysis'
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Web API adaptor
Use the WebApiAdaptor to consume custom REST APIs that follow a standard response format. This adaptor is ideal for backends that do not implement OData but provide REST endpoints returning JSON data.
Expected response format:
The Web API must return a JSON object with two properties:
-
Items: Array of data objects for the chart -
Count: Total number of records (useful for pagination)
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
import { DataManager, Query, WebApiAdaptor } from '@syncfusion/ej2-data';
Chart.Inject(ColumnSeries, Category);
let dataManager: DataManager = new DataManager({
url: 'https://services.syncfusion.com/js/production/api/orders',
adaptor: new WebApiAdaptor()
});
let query: Query = new Query();
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
//Initializing Chart Sample
series: [
{
type: 'Column',
dataSource: dataManager,
xName: 'CustomerID', yName: 'Freight', query: query
}
],
title: 'Sprint Task Analysis'
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Example response:
The Web API should structure its response as shown below. The Items array contains the actual data records, and Count indicates the total available records (supporting server-side pagination).
{
Items: [{..}, {..}, {..}, ...],
Count: 830
}
Custom adaptor
Create a custom adaptor by extending one of the built-in adaptors (typically ODataAdaptor) to add custom logic for request/response handling. Override the processResponse method to transform or enrich the response data. Common use cases include adding serial numbers, reformatting dates, or adding computed fields before the chart renders the data.
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
import { DataManager, Query, ODataAdaptor } from '@syncfusion/ej2-data';
Chart.Inject(ColumnSeries, Category);
class SerialNoAdaptor extends ODataAdaptor {
processResponse(): Object {
let i: number = 0;
// calling base class processResponse function
let original: {result: Object[], count: number} = super.processResponse.apply(this, arguments);
// adding serial number
original.result.forEach((item: Object) => item['Sno'] = ++i);
return { result: original.result, count: original.count };
}
}
let dataManager: DataManager = new DataManager({
url: 'https://services.syncfusion.com/js/production/api/orders',
adaptor: new SerialNoAdaptor()
});
let query: Query = new Query();
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
//Initializing Chart Sample
series: [
{
type: 'Column',
dataSource: dataManager,
xName: 'CustomerID', yName: 'Sno', query: query
}
],
title: 'Sprint Task Analysis'
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Offline mode
When using remote data binding, all filtering, sorting, and pagination normally happen on the server. To improve responsiveness and reduce server load, enable offline mode: the chart loads all data once during initialization, then handles all interactions client-side. Set the offline property of DataManager to true to activate this behavior.
Use offline mode when:
- Your dataset is relatively small (fits comfortably in browser memory)
- You want instant filtering and sorting without server round-trips
- Network latency is a significant usability concern
- You prefer to minimize server requests during user interactions
Caution: Offline mode loads the entire dataset at once, which may impact initial load time and memory usage for large datasets.
import { Chart, ColumnSeries, Category } from '@syncfusion/ej2-charts';
import { DataManager, Query, ODataAdaptor } from '@syncfusion/ej2-data';
Chart.Inject(ColumnSeries, Category);
let dataManager: DataManager = new DataManager({
url: 'https://services.syncfusion.com/js/production/api/orders',
adaptor: new ODataAdaptor(),
offline: true
});
let query: Query = new Query();
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
//Initializing Chart Sample
series: [
{
type: 'Column',
dataSource: dataManager,
xName: 'CustomerID', yName: 'Freight', query: query
}
],
title: 'Sprint Task Analysis'
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Lazy loading
Lazy loading enables on-demand data retrieval, loading only the data required for the currently visible range. The chart fires the scrollEnd event when the user scrolls near the edge of the visible data range. In this event handler, retrieve the minimum and maximum values from the scrolled axis, request the corresponding data from your server, and append it to the chart. This approach is ideal for large datasets that would be expensive to load entirely into memory.
How lazy loading works:
- User scrolls the chart to view a different data range
-
scrollEndevent fires with current axis range information - Fetch the corresponding data from your server
- Append new data to the existing dataset
- Chart automatically re-renders with the updated data
import { Chart, ScrollBar, Zoom, IScrollEventArgs, LineSeries, Tooltip, DateTime } from '@syncfusion/ej2-charts';
import { Internationalization, DateFormatOptions } from '@syncfusion/ej2-base';
Chart.Inject(DateTime, ScrollBar, Zoom, LineSeries, Tooltip);
let intl: Internationalization = new Internationalization();
let chart: Chart = new Chart({
primaryXAxis: {
title: 'Day',
valueType: 'DateTime',
edgeLabelPlacement: 'Shift',
skeleton: 'yMMM',
skeletonType: 'Date',
scrollbarSettings: {
range: {
minimum: new Date(2009, 0, 1),
maximum: new Date(2014, 0, 1)
},
enable: true,
}
},
primaryYAxis: {
title: 'Server Load',
labelFormat: '{value}MB'
},
series: [{
dataSource: GetDateTimeData(new Date(2009, 0, 1), new Date(2009, 8, 1)),
xName: 'x', yName: 'y',
type: 'Line', animation: { enable: false },
}],
height: '450',
title: 'Network Load',
crosshair: { enable: true, lineType: 'Vertical' },
tooltip: { enable: true, shared: true },
legendSettings: { visible: true },
scrollEnd: (args: IScrollEventArgs) => {
if (lazymode.value === 'Range') {
chart.series[0].dataSource = GetDateTimeData(args.currentRange.minimum as Date, args.currentRange.maximum as Date);
}
chart.dataBind();
},
}, '#element');
function GetDateTimeData(start: Date, end: Date): { x: Date, y: number }[] {
let series1: { x: Date, y: number }[] = [];
let date: number;
let value: number = 30;
let option: DateFormatOptions = {
skeleton: 'full',
type: 'dateTime'
};
let dateParser: Function = intl.getDateParser(option);
let dateFormatter: Function = intl.getDateFormat(option);
for (let i: number = 0; start <= end; i++) {
date = Date.parse(dateParser(dateFormatter(start)));
if (Math.random() > .5) {
value += (Math.random() * 10 - 5);
} else {
value -= (Math.random() * 10 - 5);
}
if (value < 0) {
value = getRandomInt(20, 40);
}
let point1: { x: Date, y: number } = { x: new Date(date), y: Math.round(value) };
new Date(start.setDate(start.getDate() + 1));
series1.push(point1);
}
return series1;
} function getRandomInt(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Empty points
Data points with null or undefined values are treated as empty points. Empty data points are skipped and not rendered in the chart. When using the points property to define individual data items, customize empty points with the emptyPointSettings property in the series configuration. By default, empty points create a gap in the series line or bar.
Default behavior: Empty points use the Gap mode, which leaves a blank space in the chart visualization.
import { Chart, ColumnSeries, LineSeries, Category } from '@syncfusion/ej2-charts';
Chart.Inject(ColumnSeries, LineSeries, Category);
let chartData: Object[] = [
{ month: 'Jan', sales: 35 }, { month: 'Feb', sales: 28 },
{ month: 'Mar', sales: null }, { month: 'Apr', sales: 32 },
{ month: 'May', sales: 40 }, { month: 'Jun', sales: 32 },
{ month: 'Jul', sales: 35 }, { month: 'Aug', sales: undefined },
{ month: 'Sep', sales: 38 }, { month: 'Oct', sales: 30 },
{ month: 'Nov', sales: 25 }, { month: 'Dec', sales: 32 }
];
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
series:[{
dataSource: chartData,
xName: 'month',
yName: 'sales',
type: 'Column',
emptyPointSettings: {
mode: 'Gap'
}
},
{
dataSource: chartData,
xName: 'month',
yName: 'sales',
type: 'Line',
marker: { visible: true},
emptyPointSettings: {
mode: 'Average'
}
}]
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Customizing empty point
Assign a specific color to empty points by setting the fill property in the emptyPointSettings object. This allows you to visually distinguish empty data points from regular data in your chart.
import { Chart, ColumnSeries, LineSeries Category } from '@syncfusion/ej2-charts';
Chart.Inject(ColumnSeries, LineSeries, Category);
let chartData: Object[] = [
{ month: 'Jan', sales: 35 }, { month: 'Feb', sales: 28 },
{ month: 'Mar', sales: null }, { month: 'Apr', sales: 32 },
{ month: 'May', sales: 40 }, { month: 'Jun', sales: 32 },
{ month: 'Jul', sales: 35 }, { month: 'Aug', sales: undefined },
{ month: 'Sep', sales: 38 }, { month: 'Oct', sales: 30 },
{ month: 'Nov', sales: 25 }, { month: 'Dec', sales: 32 }
];
let chart: Chart = new Chart({
primaryXAxis: {
valueType: 'Category'
},
series:[{
dataSource: chartData,
xName: 'month',
yName: 'sales',
type: 'Column',
emptyPointSettings: {
mode: 'Average',
fill: 'green',
border: { color: 'black', width: 2}
}
},
{
dataSource: chartData,
xName: 'month',
yName: 'sales',
type: 'Line',
marker: { visible: true},
emptyPointSettings: {
mode: 'Zero',
fill: 'pink'
}
}]
}, '#element');<!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>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>Handling No Data
When the chart has no data available to render, use the noDataTemplate property to display a custom layout within the chart area. This template can include messages, images, icons, or interactive elements (such as a load button) to guide the user. The template maintains design consistency and improves user experience when data is unavailable. Once data becomes available, the chart automatically updates and replaces the template with the visualization.
import {
Chart, LineSeries, Category, ChartTheme,
Tooltip, ILoadedEventArgs
} from '@syncfusion/ej2-charts';
import { Button } from '@syncfusion/ej2-buttons';
/**
* Sample for No Data Template
*/
Chart.Inject(LineSeries, Category, Tooltip);
const chartData: Object[] = [
{ Month: 'January', Value: 19173 },
{ Month: 'February', Value: 17726 },
{ Month: 'March', Value: 19874 },
{ Month: 'April', Value: 19391 },
{ Month: 'May', Value: 20072 },
{ Month: 'June', Value: 19233 }
];
let checked: boolean = false;
const chart: Chart = new Chart({
title: 'Milk Production in US - 2025',
subTitle: 'Source: nass.usda.gov',
primaryXAxis: {
valueType: 'Category',
majorGridLines: { width: 0 },
majorTickLines: { width: 0 },
},
primaryYAxis: {
title: 'Production (in million pounds)',
titleStyle: { fontWeight: '600' },
majorTickLines: { width: 0 },
lineStyle: { width: 0 }
},
chartArea: {
border: { width: 0 },
},
series: [{
dataSource: [],
xName: 'Month',
yName: 'Value',
type: 'Line',
width: 2,
marker: {
visible: true, width: 7, height: 7
}
}],
tooltip: {
enable: true,
header: 'Milk Production',
format: '${point.x} : <b>${point.y}M</b>'
},
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 0;"><strong>No data available to display.</strong></p>
</div>
<div class="template-align">
<button id="loadDataBtn" style="margin-top: 15px;"></button>
</div>
</div>
`,
loaded: (args: ILoadedEventArgs) => {
const btnElem: HTMLElement | null = document.getElementById('loadDataBtn');
if (btnElem) {
const loadBtn: Button = new Button({
content: 'Load Data',
iconCss: 'e-icons e-refresh',
cssClass: 'e-outline',
isPrimary: false
});
loadBtn.appendTo(btnElem);
loadBtn.element.onclick = (): void => {
checked = !checked;
if (checked) {
chart.series[0].dataSource = chartData;
}
chart.refresh();
};
}
}
});
chart.appendTo('#element');<!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>
<style>
#noDataTemplateContainer {
height: inherit;
width: inherit;
}
.load-data-btn {
border-radius: 4px !important;
text-transform: none !important;
}
.light-bg {
background-color: #fafafa;
color: #000000;
}
.template-align img {
max-width: 150px;
/* Adjust size as needed */
max-height: 150px;
margin-top: 55px;
}
.template-align {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div id='element'></div>
</div>
</body>
</html>