Row spanning in Angular TreeGrid component
The row spanning feature in the Syncfusion® Angular TreeGrid allows merging cells in the same column vertically, creating a visually appealing and informative layout. By defining the rowSpan attribute in the queryCellInfo event, cells can be easily spanned and the appearance of the TreeGrid can be customized.
The queryCellInfo event is triggered for each cell in the TreeGrid, and allows customizing the cells in the TreeGrid. By handling this event, the rowSpan attribute can be set for a cell to achieve row spanning.
In the following demo, the Lunch Break cell spans multiple rows in the “1:00 PM” column.
import { NgModule, ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { Component, OnInit } from '@angular/core';
import { QueryCellInfoEventArgs, GridLine, Column } from '@syncfusion/ej2-angular-grids';
import { columnSpanData } from './datasource';
import { EmitType } from '@syncfusion/ej2-base';
@Component({
imports: [TreeGridModule,],
standalone: true,
selector: 'app-container',
template: `<ejs-treegrid [dataSource]='data' [height]='300' [width]='width' [gridLines]='gridLines' childMapping="subtasks" [treeColumnIndex]='1'
(queryCellInfo)='queryCellInfoEvent($event)'>
<e-columns>
<e-column field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right" isPrimaryKey=true></e-column>
<e-column field='EmployeeName' headerText='Employee Name' width='150'></e-column>
<e-column field='9:00' headerText='9:00 AM' width='120'></e-column>
<e-column field='10:00' headerText='10:00 AM' width='120'></e-column>
<e-column field='11:00' headerText='11:00 AM' width='120'></e-column>
<e-column field='12:00' headerText='12:00 PM' width='120'></e-column>
<e-column field='1:00' headerText='1:00 PM' width='120'></e-column>
<e-column field='3:00' headerText='3:00 PM' width='120'></e-column>
<e-column field='4:00' headerText='4:00 PM' width='120'></e-column>
<e-column field='5:00' headerText='5:00 PM' width='120'></e-column>
</e-columns>
</ejs-treegrid>`,
})
export class AppComponent implements OnInit {
public data?: object[];
public width?: string | number;
public gridLines?: GridLine;
public queryCellInfoEvent: EmitType<QueryCellInfoEventArgs> = (
args: QueryCellInfoEventArgs
) => {
const data: any = args.data as any;
switch (data.EmployeeID) {
case 10001:
if ((args.column as Column).field === '1:00') {
args.rowSpan = 10;
}
break;
}
};
ngOnInit(): void {
this.data = columnSpanData;
this.gridLines = 'Both';
this.width = 'auto';
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
- To disable the spanning for particular TreeGrid page, use requestType from
queryCellInfoevent argument.- The
rowSpanandcolSpanattributes can be used together to merge cells both vertically and horizontally.
Limitations
- The updateCell method does not support row spanning.
- Row spanning is not compatible with the following features:
- Virtual scrolling
- Infinite scrolling
- Row drag and drop
- Autofill
- Row or cell editing
- Batch editing
- CRUD
Row spanning implementation through API
The Syncfusion Angular TreeGrid provides an API-based approach to vertically merge cells with identical values in the same column across consecutive rows.
The row spanning feature in the Syncfusion Angular TreeGrid can be enabled using enableRowSpan property to true in the TreeGrid configuration, which significantly enhances readability and delivers a cleaner layout by eliminating repetitive data in columns such as “Status”, “Permit Status”, “Inspection Status” and “Punch List Status”.
import { NgModule, ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule,FreezeService,PageService } from '@syncfusion/ej2-angular-treegrid'
import { Component, OnInit } from '@angular/core';
import { QueryCellInfoEventArgs, GridLine, Column } from '@syncfusion/ej2-angular-grids';
import { rowSpanData } from './datasource';
import { EmitType } from '@syncfusion/ej2-base';
@Component({
imports: [TreeGridModule,],
standalone: true,
selector: 'app-container',
providers: [FreezeService,PageService],
template: `<ejs-treegrid #treegrid [dataSource]="data" childMapping="children" [treeColumnIndex]="0" [height]="300"
[enableRowSpan]="true" [rowHeight]="50" gridLines="Both" clipMode="EllipsisWithTooltip"
[enableHover]="false" [allowSelection]="false" allowPaging="true" [pageSettings]="pageSettings">
<e-columns>
<e-column field="activityName" headerText="Phase Name" width="250" freeze="Left"></e-column>
<e-column headerText="Schedule" textAlign="Center" [columns]="scheduleColumns"></e-column>
<e-column headerText="Work Status" textAlign="Center" [columns]="statusColumns"></e-column>
<e-column headerText="Compliance" textAlign="Center" [columns]="complianceColumns"></e-column>
<e-column headerText="Personnel" textAlign="Center" [columns]="personnelColumns"></e-column>
<e-column headerText="Materials" textAlign="Center" [columns]="materialsColumns"></e-column>
<e-column headerText="Cost Summary" textAlign="Center" [columns]="budgetColumns"></e-column>
</e-columns>
</ejs-treegrid>`,
})
export class AppComponent implements OnInit {
public data?: Object[];
public pageSettings?: Object;
public scheduleColumns?: Object[];
public personnelColumns?: Object[];
public statusColumns?: Object[];
public complianceColumns?: Object[];
public materialsColumns?: Object[];
public budgetColumns?: Object[];
ngOnInit(): void {
this.data = rowSpanData;
this.pageSettings= { pageSizeMode: 'All', pageSize: 18 };
this.scheduleColumns = [
{ field: 'startDate', headerText: 'Start Date', type: 'date', format: 'MM/dd/yyyy', width: 140, textAlign: 'Center' },
{ field: 'endDate', headerText: 'End Date', type: 'date', format: 'MM/dd/yyyy', width: 140, textAlign: 'Center' }
];
this.personnelColumns = [
{
field: 'supervisor',
headerText: 'Supervisor',
width: 180,
},
{ field: 'team', headerText: 'Crew', width: 200 }
];
this.statusColumns = [
{ field: 'status', headerText: 'Status', width: 180, textAlign: 'Center' }
];
this.complianceColumns = [
{ field: 'permitStatus', headerText: 'Permit Status', width: 160, textAlign: 'Center' },
{ field: 'inspectionDate', headerText: 'Inspection Date', width: 180, type: 'date', format: 'MM/dd/yyyy', textAlign: 'Center' },
{ field: 'inspectionStatus', headerText: 'Inspection Status', width: 180, textAlign: 'Center' },
{ field: 'punchListStatus', headerText: 'Punch List Status', width: 180, textAlign: 'Center' }
];
this.materialsColumns = [
{ field: 'materialUsed', headerText: 'Materials Used', width: 180, textAlign: 'Center' },
{ field: 'materialCost', headerText: 'Material Cost', width: 140, format: 'C2', textAlign: 'Right', enableRowSpan: false}
];
this.budgetColumns = [
{ field: 'totalBudget', headerText: 'Planned Budget', width: 140, format: 'C2', textAlign: 'Center', enableRowSpan: false},
{ field: 'paidToDate', headerText: 'Actual Spend', width: 140, format: 'C2', textAlign: 'Center', enableRowSpan: false}
];
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));In the sample, row spanning is disabled at the column level for the price based columns such as “Planned Budget” and “Actual Spend” by setting each column’s
enableRowSpanproperty to false.
Limitation
- Virtualization
- Infinite Scrolling
- Row Drag and Drop
- Column Virtualization
- Detail Template
- Editing
- Export