The immutable mode optimizes the Grid re-rendering performance by using the object reference and deep compare
concept. When performing the Grid actions, it will only re-render the modified or newly added rows and prevent the re-rendering of the unchanged rows.
To enable this feature, you have to set the enableImmutableMode
property as true.
- This feature uses the primary key value for data comparison. So, you need to provide the
isPrimaryKey
column.
import { Grid, Page } from '@syncfusion/ej2-grids';
import { data } from './datasource.ts';
import { Button } from '@syncfusion/ej2-buttons';
Grid.Inject(Page);
let immutableStart;
let normalStart;
let primaryKey = 0;
let immutableInit = true;
let init = true;
let immutableGrid: Grid = new Grid({
dataSource: data,
allowPaging: true,
pageSettings: { pageSize: 50 },
enableImmutableMode: true,
beforeDataBound: () => {
immutableStart = new Date().getTime();
},
dataBound: ()=> {
let val = immutableInit ? '' : new Date().getTime() - immutableStart;
document.getElementById('immutableDelete').innerHTML = 'Immutable rendering Time: ' + "<b>" + val + "</b>" + '<b>ms</b>';
immutableStart = 0; immutableInit = false;
},
columns: [
{ field: 'OrderID', headerText: 'Order ID', isPrimaryKey: true, textAlign: 'Right', width: 120 },
{ field: 'ProductName', headerText: 'Product Name', width: 160 },
{ field: 'ProductID', headerText: 'Product ID', textAlign: 'Right', width: 120 },
{ field: 'CustomerID', headerText: 'Customer ID', width: 120 },
{ field: 'CustomerName', headerText: 'Customer Name', width: 160 }
],
height: 240
});
immutableGrid.appendTo('#immutable');
document.getElementById('delete').addEventListener('click', function(e) {
(immutableGrid.dataSource as Object[]).splice(0, 5);
normalGrid.setProperties({ dataSource: immutableGrid.dataSource });
immutableGrid.setProperties({ dataSource: immutableGrid.dataSource });
});
document.getElementById('addtop').addEventListener('click', function(e) {
let addedRecords = [
{'OrderID': ++primaryKey, 'ProductName': 'Chai', 'ProductID': 'Sasquatch Ale', 'CustomerID': 'QUEDE', 'CustomerName': 'Yoshi Tannamuri'},
{'OrderID': ++primaryKey, 'ProductName': 'Georg Pipps', 'ProductID': 'Valkoinen suklaa', 'CustomerID': 'RATTC', 'CustomerName': 'Martín Sommer'},
{'OrderID': ++primaryKey, 'ProductName': 'Yoshi Tannamuri', 'ProductID': 'Gula Malacca', 'CustomerID': 'COMMI', 'CustomerName': 'Ann Devon'},
{'OrderID': ++primaryKey, 'ProductName': 'Palle Ibsen', 'ProductID': 'Rogede sild', 'CustomerID': 'RATTC', 'CustomerName': 'Paula Wilson'},
{'OrderID': ++primaryKey, 'ProductName': 'Francisco Chang', 'ProductID': 'Mascarpone Fabioli', 'CustomerID': 'ROMEY', 'CustomerName': 'Jose Pavarotti'}
]
let aData = (addedRecords as Object[]).concat(immutableGrid.dataSource);
normalGrid.setProperties({ dataSource: aData });
immutableGrid.setProperties({ dataSource: aData });
});
document.getElementById('addbottom').addEventListener('click', function(e) {
let addedRecords = [
{'OrderID': ++primaryKey, 'ProductName': 'Chai', 'ProductID': 'Sasquatch Ale', 'CustomerID': 'QUEDE', 'CustomerName': 'Yoshi Tannamuri'},
{'OrderID': ++primaryKey, 'ProductName': 'Georg Pipps', 'ProductID': 'Valkoinen suklaa', 'CustomerID': 'RATTC', 'CustomerName': 'Martín Sommer'},
{'OrderID': ++primaryKey, 'ProductName': 'Yoshi Tannamuri', 'ProductID': 'Gula Malacca', 'CustomerID': 'COMMI', 'CustomerName': 'Ann Devon'},
{'OrderID': ++primaryKey, 'ProductName': 'Palle Ibsen', 'ProductID': 'Rogede sild', 'CustomerID': 'RATTC', 'CustomerName': 'Paula Wilson'},
{'OrderID': ++primaryKey, 'ProductName': 'Francisco Chang', 'ProductID': 'Mascarpone Fabioli', 'CustomerID': 'ROMEY', 'CustomerName': 'Jose Pavarotti'}
]
let aData = (immutableGrid.dataSource as Object[]).concat(addedRecords);
normalGrid.setProperties({ dataSource: aData });
immutableGrid.setProperties({ dataSource: aData });
});
document.getElementById('reverse').addEventListener('click', function(e) {
let aData = (immutableGrid.dataSource as Object[]).reverse();
normalGrid.setProperties({ dataSource: aData });
immutableGrid.setProperties({ dataSource: aData });
});
document.getElementById('paging').addEventListener('click', function(e) {
let totalPage = (immutableGrid.dataSource as Object[]).length / immutableGrid.pageSettings.pageSize;
let page = Math.floor(Math.random() * totalPage) + 1;
normalGrid.setProperties({ pageSettings: { currentPage: page } });
immutableGrid.setProperties({ pageSettings: { currentPage: page } });
});
let normalGrid: Grid = new Grid({
dataSource: data,
allowPaging: true,
pageSettings: { pageSize: 50 },
beforeDataBound: () => {
normalStart = new Date().getTime();
},
dataBound: ()=> {
let val = init ? '' : new Date().getTime() - normalStart;
document.getElementById('normalDelete').innerHTML = 'Normal rendering Time: ' + "<b>" + val + "</b>" + '<b>ms</b>';
normalStart = 0; init = false;
},
columns: [
{ field: 'OrderID', headerText: 'Order ID', isPrimaryKey: true, textAlign: 'Right', width: 120 },
{ field: 'ProductName', headerText: 'Product Name', width: 160 },
{ field: 'ProductID', headerText: 'Product ID', textAlign: 'Right', width: 120 },
{ field: 'CustomerID', headerText: 'Customer ID', width: 120 },
{ field: 'CustomerName', headerText: 'Customer Name', width: 160 }
],
height: 240
});
normalGrid.appendTo('#normal');
<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Grid</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Grid Control" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-grids/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-navigations/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-dropdowns/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-lists/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-inputs/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-calendars/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/21.1.35/ej2-splitbuttons/styles/material.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>
.immutablegrid,
.normalgrid {
pointer-events: none;
}
</style>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<script id="template" type="text/x-template">
<div class="image">
<img src="${Id}.png" alt="${Id}" />
</div>
</script>
<table>
<tbody>
<tr>
<td>
<span id='immutableDelete'></span>
</td>
</tr>
<tr>
<td>
<span id='normalDelete'></span>
</td>
</tr>
<tr>
<td>
<div>
<button id="addtop" class="e-control e-btn e-lib e-info">Add 5 rows at top</button>
<button id="addbottom" class="e-control e-btn e-lib e-info">Add 5 rows at bottom</button>
<button id="delete" class="e-control e-btn e-lib e-info">Delete 5 rows</button>
<button id="reverse" class="e-control e-btn e-lib e-info">Sort Order ID</button>
<button id="paging" class="e-control e-btn e-lib e-info">Paging</button>
</div>
</td>
</tr>
<tr>
<td>
<span><b>Immutable Grid</b></span>
<div id='immutable' class="immutablegrid"></div>
</td>
</tr>
<tr>
<td>
<span><b>Normal Grid</b></span>
<div id='normal' class="normalgrid"></div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
The following features are not supported in the immutable mode: