Column spanning in EJ2 JavaScript Grid control
11 Sep 202524 minutes to read
The column spanning feature in the Syncfusion® Grid allows you to merge adjacent cells horizontally, creating a visually appealing and informative layout. By defining the colSpan attribute in the queryCellInfo event, you can easily span cells and customize the appearance of the grid.
In the following demo, Employee Davolio doing analysis from 9.00 AM to 10.00 AM, so that cells have spanned.
var grid = new ej.grids.Grid({
dataSource: columnSpanData,
queryCellInfo: QueryCellEvent,
gridLines: 'Both',
columns: [
{ field: 'EmployeeID', headerText: 'Employee ID', isPrimaryKey: true, textAlign: 'Right', width: 150 },
{ field: 'EmployeeName', headerText: 'Employee Name', width: 200 },
{ field: '9:00', headerText: '9.00 AM', width: 120 },
{ field: '9:30', headerText: '9.30 AM', width: 120 },
{ field: '10:00', headerText: '10.00 AM', width: 120 },
{ field: '10:30', headerText: '10.30 AM', width: 120 },
{ field: '11:00', headerText: '11.00 AM', width: 120 },
{ field: '11:30', headerText: '11.30 AM', width: 120 },
{ field: '12:00', headerText: '12.00 PM', width: 120 },
{ field: '12:30', headerText: '12.30 PM', width: 120 },
{ field: '2:30', headerText: '2.30 PM', width: 120 },
{ field: '3:00', headerText: '3.00 PM', width: 120 },
{ field: '3:30', headerText: '3.30 PM', width: 120 },
{ field: '4:00', headerText: '4.00 PM', width: 120 },
{ field: '4:30', headerText: '4.30 PM', width: 120 },
{ field: '5:00', headerText: '5.00 PM', width: 120 }
],
width: 'auto',
height: 'auto',
allowTextWrap: true
});
grid.appendTo('#Grid');
function QueryCellEvent(args) {
var data = args.data;
switch (data.EmployeeID) {
case 10001:
if (args.column.field === '9:00' || args.column.field === '2:30' || args.column.field === '4:30') {
args.colSpan = 2;
} else if (args.column.field === '11:00') {
args.colSpan = 3;
}
break;
case 10002:
if (args.column.field === '9:30' || args.column.field === '2:30' ||
args.column.field === '4:30') {
args.colSpan = 3;
} else if (args.column.field === '11:00') {
args.colSpan = 4;
}
break;
case 10003:
if (args.column.field === '9:00' || args.column.field === '11:30') {
args.colSpan = 3;
} else if (args.column.field === '10:30' || args.column.field === '3:30' ||
args.column.field === '4:30' || args.column.field === '2:30') {
args.colSpan = 2;
}
break;
case 10004:
if (args.column.field === '9:00') {
args.colSpan = 3;
} else if (args.column.field === '11:00') {
args.colSpan = 4;
} else if (args.column.field === '4:00' || args.column.field === '2:30') {
args.colSpan = 2;
}
break;
case 10005:
if (args.column.field === '9:00') {
args.colSpan = 4;
} else if (args.column.field === '11:30') {
args.colSpan = 3;
} else if (args.column.field === '3:30' || args.column.field === '4:30' || args.column.field === '2:30') {
args.colSpan = 2;
}
break;
case 10006:
if (args.column.field === '9:00' || args.column.field === '4:30' ||
args.column.field === '2:30' || args.column.field === '3:30') {
args.colSpan = 2;
} else if (args.column.field === '10:00' || args.column.field === '11:30') {
args.colSpan = 3;
}
break;
case 10007:
if (args.column.field === '9:00' || args.column.field === '3:00' || args.column.field === '10:30') {
args.colSpan = 2;
} else if (args.column.field === '11:30' || args.column.field === '4:00') {
args.colSpan = 3;
}
break;
case 10008:
if (args.column.field === '9:00' || args.column.field === '10:30' || args.column.field === '2:30') {
args.colSpan = 3;
} else if (args.column.field === '4:00') {
args.colSpan = 2;
}
break;
case 10009:
if (args.column.field === '9:00' || args.column.field === '11:30') {
args.colSpan = 3;
} else if (args.column.field === '4:30' || args.column.field === '2:30') {
args.colSpan = 2;
}
break;
case 100010:
if (args.column.field === '9:00' || args.column.field === '2:30' ||
args.column.field === '4:00' || args.column.field === '11:30') {
args.colSpan = 3;
} else if (args.column.field === '10:30') {
args.colSpan = 2;
}
break;
}
}<!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="https://cdn.syncfusion.com/ej2/31.2.12/ej2-base/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-buttons/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-popups/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-navigations/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-dropdowns/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-lists/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-inputs/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-calendars/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-splitbuttons/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-grids/styles/bootstrap5.css" rel="stylesheet">
<script src="https://cdn.syncfusion.com/ej2/31.2.12/dist/ej2.min.js" type="text/javascript"></script>
<script src="es5-datasource.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id="container">
<div id="Grid"></div>
</div>
<script>
var ele = document.getElementById('container');
if(ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body></html>Change the border color while column spanning
You can change the border color for the spanned cells by the using queryCellInfo event. This event triggers before the cell element is appended to the Grid element.
var grid = new ej.grids.Grid({
dataSource: columnSpanData,
queryCellInfo: QueryCellEvent,
gridLines: 'Both',
columns: [
{ field: 'EmployeeID', headerText: 'Employee ID', isPrimaryKey: true, textAlign: 'Right', width: 150 },
{ field: 'EmployeeName', headerText: 'Employee Name', width: 200 },
{ field: '9:00', headerText: '9.00 AM', width: 120 },
{ field: '9:30', headerText: '9.30 AM', width: 120 },
{ field: '10:00', headerText: '10.00 AM', width: 120 },
{ field: '10:30', headerText: '10.30 AM', width: 120 },
{ field: '11:00', headerText: '11.00 AM', width: 120 },
{ field: '11:30', headerText: '11.30 AM', width: 120 },
{ field: '12:00', headerText: '12.00 PM', width: 120 },
{ field: '12:30', headerText: '12.30 PM', width: 120 },
{ field: '2:30', headerText: '2.30 PM', width: 120 },
{ field: '3:00', headerText: '3.00 PM', width: 120 },
{ field: '3:30', headerText: '3.30 PM', width: 120 },
{ field: '4:00', headerText: '4.00 PM', width: 120 },
{ field: '4:30', headerText: '4.30 PM', width: 120 },
{ field: '5:00', headerText: '5.00 PM', width: 120 }
],
width: 'auto',
height: 'auto',
allowTextWrap: true
});
grid.appendTo('#Grid');
function QueryCellEvent(args) {
var data = args.data;
switch (data.EmployeeID) {
case 10001:
if (
args.column.field === '9:00' ||
args.column.field === '2:30' ||
args.column.field === '4:30'
) {
args.colSpan = 2;
} else if (args.column.field === '11:00') {
args.colSpan = 3;
}
break;
case 10002:
if (
args.column.field === '9:30' ||
args.column.field === '2:30' ||
args.column.field === '4:30'
) {
args.colSpan = 3;
} else if (args.column.field === '11:00') {
args.colSpan = 4;
}
break;
case 10003:
if (args.column.field === '9:00' || args.column.field === '11:30') {
args.colSpan = 3;
} else if (
args.column.field === '10:30' ||
args.column.field === '3:30' ||
args.column.field === '4:30' ||
args.column.field === '2:30'
) {
args.colSpan = 2;
}
break;
case 10004:
if (args.column.field === '9:00') {
args.colSpan = 3;
} else if (args.column.field === '11:00') {
args.colSpan = 4;
} else if (args.column.field === '4:00' || args.column.field === '2:30') {
args.colSpan = 2;
}
break;
case 10005:
if (args.column.field === '9:00') {
args.colSpan = 4;
} else if (args.column.field === '11:30') {
args.colSpan = 3;
} else if (
args.column.field === '3:30' ||
args.column.field === '4:30' ||
args.column.field === '2:30'
) {
args.colSpan = 2;
}
break;
case 10006:
if (
args.column.field === '9:00' ||
args.column.field === '4:30' ||
args.column.field === '2:30' ||
args.column.field === '3:30'
) {
args.colSpan = 2;
} else if (
args.column.field === '10:00' ||
args.column.field === '11:30'
) {
args.colSpan = 3;
}
break;
case 10007:
if (
args.column.field === '9:00' ||
args.column.field === '3:00' ||
args.column.field === '10:30'
) {
args.colSpan = 2;
} else if (
args.column.field === '11:30' ||
args.column.field === '4:00'
) {
args.colSpan = 3;
}
break;
case 10008:
if (
args.column.field === '9:00' ||
args.column.field === '10:30' ||
args.column.field === '2:30'
) {
args.colSpan = 3;
} else if (args.column.field === '4:00') {
args.colSpan = 2;
}
break;
default:
extendQueryCellEvent(args, data.EmployeeID);
}
if (args.colSpan > 1) {
args.cell.style.border = '1px solid red';
}
}
function extendQueryCellEvent(args, value) {
switch (value) {
case 10009:
if (args.column.field === '9:00' || args.column.field === '11:30') {
args.colSpan = 3;
} else if (args.column.field === '4:30' || args.column.field === '2:30') {
args.colSpan = 2;
}
break;
case 100010:
if (
args.column.field === '9:00' ||
args.column.field === '2:30' ||
args.column.field === '4:00' ||
args.column.field === '11:30'
) {
args.colSpan = 3;
} else if (args.column.field === '10:30') {
args.colSpan = 2;
}
break;
}
}<!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="https://cdn.syncfusion.com/ej2/31.2.12/ej2-base/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-buttons/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-popups/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-navigations/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-dropdowns/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-lists/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-inputs/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-calendars/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-splitbuttons/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-grids/styles/bootstrap5.css" rel="stylesheet">
<script src="https://cdn.syncfusion.com/ej2/31.2.12/dist/ej2.min.js" type="text/javascript"></script>
<script src="es5-datasource.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id="container">
<div id="Grid"></div>
</div>
<script>
var ele = document.getElementById('container');
if(ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body></html>Limitations
- The updateCell method does not support column spanning.
- Column spanning is not compatible with the following features:
- Virtual scrolling
- Infinite scrolling
- Grouping
- Autofill
Column spanning using enableColumnSpan property
The Syncfusion Grid introduces a simplified approach to horizontally merge cells using the enableColumnSpan property.
When the enableColumnSpan property is enabled, the Grid automatically merges cells with matching data across adjacent columns without requiring manual span configuration using the queryCellInfo event. These merged cells are visually combined into a single cell, improving readability.
Here is an example of how to use the enableColumnSpan property to merge cells horizontally:
var grid = new ej.grids.Grid({
dataSource: shiftPlanData,
gridLines: 'Both',
allowSorting: true,
enableColumnSpan: true,
columns: [
{ field: 'Name', headerText: 'Doctor Name', width: 170, textAlign: 'Center', freeze: 'Left', template: '#template' },
{ field: 'Time9AM', headerText: '9:00 AM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time10AM', headerText: '10:00 AM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time11AM', headerText: '11:00 AM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time12PM', headerText: '12:00 PM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time1PM', headerText: '1:00 PM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time2PM', headerText: '2:00 PM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time3PM', headerText: '3:00 PM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time4PM', headerText: '4:00 PM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time5PM', headerText: '5:00 PM', width: 120, textAlign: 'Center', allowSorting: false },
{ field: 'Time6PM', headerText: '6:00 PM', width: 120, textAlign: 'Center', allowSorting: false},
{ field: 'Time7PM', headerText: '7:00 PM', width: 120, textAlign: 'Center', allowSorting: false }
],
width: 'auto',
height: 450,
allowTextWrap: true,
textWrapSettings: { wrapMode: 'Content' },
});
grid.appendTo('#Grid');<!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="https://cdn.syncfusion.com/ej2/31.2.12/ej2-base/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-buttons/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-popups/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-navigations/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-dropdowns/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-lists/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-inputs/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-calendars/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-splitbuttons/styles/bootstrap5.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/31.2.12/ej2-grids/styles/bootstrap5.css" rel="stylesheet">
<script src="https://cdn.syncfusion.com/ej2/31.2.12/dist/ej2.min.js" type="text/javascript"></script>
<script src="es5-datasource.js" type="text/javascript"></script>
<style>
body{
touch-action:none;
}
.doctor-designation {
font-size: 12px;
color: #7f8c8d;
font-weight: normal;
}
.doctor-name {
margin-bottom: 5px;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id="container">
<script id="template" type="text/x-template">
<div class="doctor-name">${Name}</div>
<div class="doctor-designation">${Designation}</div>
</script>
<div id="Grid"></div>
</div>
<script>
var ele = document.getElementById('container');
if(ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body></html>You can also control spanning at the column level. To prevent merging for specific columns, set
enableColumnSpanto false in the column definition.
Limitation
- Virtualization
- Infinite Scrolling
- Lazy Load Grouping
- Row Drag and Drop
- Column Virtualization
- Detail Template
- Editing
- Export
- Foreign Key
- Hierarchy Grid