Row spanning in React TreeGrid

The row spanning feature in the Syncfusion® React 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.

In the following demo, the Lunch Break cell spans multiple rows in the “1:00 PM” column.

import { ColumnDirective, ColumnsDirective, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';
import { rowSpanData } from './datasource';
function App() {
    const queryCellInfoEvent = (args) => {
        const col = args.column;
        const data = args.data;
        switch (data.EmployeeID) {
            case 10001:
                if (col.field === '1:00') {
                    args.rowSpan = 10;
                }
                break;
        }
    };
    return (<div className='control-pane'>
        <div className='control-section'>
            <TreeGridComponent dataSource={rowSpanData} queryCellInfo={queryCellInfoEvent} treeColumnIndex={1} childMapping='subtasks' height='auto' width='auto' gridLines='Both'>
                <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign='Right'/>
                    <ColumnDirective field='EmployeeName' headerText='Employee Name' width='150'/>
                    <ColumnDirective field='9:00' headerText='9:00 AM' width='120'/>
                    <ColumnDirective field='10:00' headerText='10:00 AM' width='120'/>
                    <ColumnDirective field='11:00' headerText='11:00 AM' width='120'/>
                    <ColumnDirective field='12:00' headerText='12:00 PM' width='120'/>
                    <ColumnDirective field='1:00' headerText='1:00 PM' width='120'/>
                    <ColumnDirective field='3:00' headerText='3:00 PM' width='120'/>
                    <ColumnDirective field='4:00' headerText='4:00 PM' width='120'/>
                    <ColumnDirective field='5:00' headerText='5:00 PM' width='120'/>
                </ColumnsDirective>
            </TreeGridComponent>
        </div>
    </div>);
}
;
export default App;
import { Column, ColumnDirective, ColumnsDirective, TreeGridComponent } from '@syncfusion/ej2-react-treegrid';
import { QueryCellInfoEventArgs } from '@syncfusion/ej2-react-grids';
import * as React from 'react';
import { rowSpanData } from './datasource';

function App() {
    const queryCellInfoEvent = (args: QueryCellInfoEventArgs) => {
        const col: Column = args.column as Column;
        const data = args.data;
        switch (data.EmployeeID) {
            case 10001:
                if (col.field === '1:00') {
                    args.rowSpan = 10;
                }
                break;
        }
    };
    return (<div className='control-pane'>
        <div className='control-section'>
            <TreeGridComponent dataSource={rowSpanData} queryCellInfo={queryCellInfoEvent} treeColumnIndex={1} childMapping='subtasks' height='auto' width='auto' gridLines='Both' >
                <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign='Right' />
                    <ColumnDirective field='EmployeeName' headerText='Employee Name' width='150' />
                    <ColumnDirective field='9:00' headerText='9:00 AM' width='120' />
                    <ColumnDirective field='10:00' headerText='10:00 AM' width='120' />
                    <ColumnDirective field='11:00' headerText='11:00 AM' width='120' />
                    <ColumnDirective field='12:00' headerText='12:00 PM' width='120' />
                    <ColumnDirective field='1:00' headerText='1:00 PM' width='120' />
                    <ColumnDirective field='3:00' headerText='3:00 PM' width='120' />
                    <ColumnDirective field='4:00' headerText='4:00 PM' width='120' />
                    <ColumnDirective field='5:00' headerText='5:00 PM' width='120' />
                </ColumnsDirective>
            </TreeGridComponent>
        </div>
    </div>)
};
export default App;

Limitations

Row spanning in the React TreeGrid has the following limitations:

  • The updateCell method does not support row spanning.
  • Row spanning is not compatible with the following features:
    1. Virtual scrolling
    2. Infinite scrolling

When using row spanning, ensure that the spanned cells do not interfere with TreeGrid operations such as sorting, filtering, or editing, as this may lead to unexpected behavior.

Row spanning implementation through API

The Syncfusion React 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 React 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 * as React from "react";
import { createRoot } from "react-dom/client";
import {
  ColumnDirective,
  ColumnsDirective,
  TreeGridComponent,
  Inject,
  Page,
  Freeze,
} from "@syncfusion/ej2-react-treegrid";
import { rowSpanData } from "./datasource";

function App() {
  return (
    <div className="control-pane">
      <div className="control-section">
        <TreeGridComponent
          dataSource={rowSpanData}
          enableHover={false}
          allowSelection={false}
          allowPaging={true}
          pageSettings=
          rowHeight={50}
          gridLines="Both"
          enableRowSpan={true}
          height={315}
          childMapping="children"
          treeColumnIndex={0}
          clipMode="EllipsisWithTooltip"
        >
          <ColumnsDirective>
            <ColumnDirective
              field="activityName"
              headerText="Phase Name"
              width="250"
              freeze="Left"
            />
            <ColumnDirective
              headerText="Schedule"
              textAlign="Center"
              columns={[
                {
                  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",
                },
              ]}
            />
            <ColumnDirective
              headerText="Work Status"
              textAlign="Center"
              columns={[
                {
                  field: "status",
                  headerText: "Status",
                  width: 180,
                  textAlign: "Center",
                },
              ]}
            />
            <ColumnDirective
              headerText="Compliance"
              textAlign="Center"
              columns={[
                {
                  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",
                },
              ]}
            />
            <ColumnDirective
              headerText="Personnel"
              textAlign="Center"
              columns={[
                { field: "supervisor", headerText: "Supervisor", width: 180 },
                { field: "team", headerText: "Crew", width: 200 },
              ]}
            />
            <ColumnDirective
              headerText="Materials"
              textAlign="Center"
              columns={[
                {
                  field: "materialUsed",
                  headerText: "Materials Used",
                  width: 180,
                  textAlign: "Center",
                },
                {
                  field: "materialCost",
                  headerText: "Material Cost",
                  width: 140,
                  format: "C2",
                  textAlign: "Right",
                  enableRowSpan: false,
                },
              ]}
            />
            <ColumnDirective
              headerText="Cost Summary"
              textAlign="Center"
              columns={[
                {
                  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,
                },
              ]}
            />
          </ColumnsDirective>
          <Inject services={[Freeze, Page]} />
        </TreeGridComponent>
      </div>
    </div>
  );
}
export default App;
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import {
  ColumnDirective,
  ColumnsDirective,
  TreeGridComponent,
  Inject,
  Page,
  Freeze,
} from "@syncfusion/ej2-react-treegrid";
import { rowSpanData } from "./datasource";

function App() {
  return (<div className='control-pane'>
    <div className='control-section'>
    <TreeGridComponent
          dataSource={rowSpanData}
          enableHover={false}
          allowSelection={false}
          allowPaging={true}
          pageSettings=
          rowHeight={50}
          gridLines="Both"
          enableRowSpan={true}
          height={315}
          childMapping="children"
          treeColumnIndex={0}
          clipMode="EllipsisWithTooltip"
        >
          <ColumnsDirective>
            <ColumnDirective
              field="activityName"
              headerText="Phase Name"
              width="250"
              freeze="Left"
            ></ColumnDirective>
            <ColumnDirective
              headerText="Schedule"
              textAlign="Center"
              columns={[
                {
                  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",
                },
              ]}
            ></ColumnDirective>
            <ColumnDirective
              headerText="Work Status"
              textAlign="Center"
              columns={[
                {
                  field: "status",
                  headerText: "Status",
                  width: 180,
                  textAlign: "Center",
                },
              ]}
            ></ColumnDirective>
            <ColumnDirective
              headerText="Compliance"
              textAlign="Center"
              columns={[
                {
                  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",
                },
              ]}
            ></ColumnDirective>
            <ColumnDirective
              headerText="Personnel"
              textAlign="Center"
              columns={[
                { field: "supervisor", headerText: "Supervisor", width: 180 },
                { field: "team", headerText: "Crew", width: 200 },
              ]}
            ></ColumnDirective>
            <ColumnDirective
              headerText="Materials"
              textAlign="Center"
              columns={[
                {
                  field: "materialUsed",
                  headerText: "Materials Used",
                  width: 180,
                  textAlign: "Center",
                },
                {
                  field: "materialCost",
                  headerText: "Material Cost",
                  width: 140,
                  format: "C2",
                  textAlign: "Right",
                  enableRowSpan: false,
                },
              ]}
            ></ColumnDirective>
            <ColumnDirective
              headerText="Cost Summary"
              textAlign="Center"
              columns={[
                {
                  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,
                },
              ]}
            ></ColumnDirective>
          </ColumnsDirective>
          <Inject services={[Freeze, Page]} />
        </TreeGridComponent>
      </div>
    </div>
  );
};
export default App;

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 enableRowSpan property to false.

Limitations

Row spanning feature is not compatible with all the features which are available in TreeGrid and it has limited features support. Here we have listed out the features which are not compatible with row spanning feature.

  • Virtualization
  • Infinite Scrolling
  • Row Drag and Drop
  • Column Virtualization
  • Detail Template
  • Editing
  • Export