Row spanning in Vue TreeGrid

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

<template>
  <div id="app">
    <ejs-treegrid
      :dataSource="data"
      :treeColumnIndex="1"
      childMapping="subtasks"
      height="auto"
      width="auto"
      gridLines="Both"
      queryCellInfo="queryCellInfoEvent"
    >
      <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>
  </div>
</template>
<script setup>

import { TreeGridComponent as EjsTreegrid, ColumnDirective as EColumn, ColumnsDirective as EColumns } from "@syncfusion/ej2-vue-treegrid";
import { rowSpanData } from "./datasource.js";

const data = rowSpanData;

const queryCellInfoEvent: function (args) {
      let data = args.data;
      switch (data.EmployeeID) {
        case 10001:
          if (args.column.field === "1:00") {
            args.rowSpan = 10;
          }
          break;
      }
    };
</script>
<template>
  <div id="app">
    <ejs-treegrid
      :dataSource="data"
      :treeColumnIndex="1"
      childMapping="subtasks"
      height="auto"
      width="auto"
      gridLines="Both"
      :queryCellInfo="queryCellInfoEvent"
    >
      <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>
  </div>
</template>
<script>

import {
  TreeGridComponent,
  ColumnsDirective,
  ColumnDirective,
} from "@syncfusion/ej2-vue-treegrid";
import { rowSpanData } from "./datasource.js";
export default {
  name: "App",
  components: {
    "ejs-grid": TreeGridComponent,
    "e-columns": ColumnsDirective,
    "e-column": ColumnDirective,
  },
  data: () => {
    return {
      data: rowSpanData,
    };
  },
  methods: {
    queryCellInfoEvent: function (args) {
      let data = args.data;
      switch (data.EmployeeID) {
        case 10001:
          if (args.column.field === "1:00") {
            args.rowSpan = 10;
          }
          break;
      }
    },
  },
};
</script>

Limitations

Row spanning in the Vue 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 via API

The row spanning feature in the Syncfusion® Vue TreeGrid allows automatically merging cells with identical values in the same column across consecutive rows. This significantly enhances readability and delivers a cleaner layout by eliminating repetitive data such as “Status”, “Permit Status”, “Inspection Status” and “Punch List Status”.

To enable row spanning, set the enableRowSpan property to true in the TreeGrid configuration.

<template>
  <div id="app">
    <ejs-treegrid
      :dataSource="data"
      childMapping="children"
      :treeColumnIndex="0"
      :enableRowSpan="true"
      :height="400"
      gridLines="Both"
      :enableHover="false"
      :allowSelection="false"
      :allowPaging="true"
      :pageSettings="pageSettings"
      clipMode="EllipsisWithTooltip"
    >
      <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>
  </div>
</template>
<script setup>
import {
  TreeGridComponent as EjsTreegrid,
  ColumnDirective as EColumn,
  ColumnsDirective as EColumns,
} from "@syncfusion/ej2-vue-treegrid";
import { rowSpanData } from "./datasource.js";

const data = rowSpanData;
const pageSettings = { pageSize: 18, pageSizeMode: 'All' };
const 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' }
];
     const personnelColumns: [
        {
          field: 'supervisor',
          headerText: 'Supervisor',
          width: 180,
        },
        { field: 'team', headerText: 'Crew', width: 200 }
      ];
      const statusColumns: [
        { field: 'status', headerText: 'Status', width: 180, textAlign: 'Center' }
      ];
      const 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' }
      ];
      const materialsColumns: [
        { field: 'materialUsed', headerText: 'Materials Used', width: 180, textAlign: 'Center' },
        { field: 'materialCost', headerText: 'Material Cost', width: 140, format: 'C2', textAlign: 'Right', enableRowSpan: false }
      ];
      const 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 }
      ];
</script>
<template>
<div id="app">
      <ejs-treegrid :dataSource="data" childMapping="children" :treeColumnIndex="0" :enableRowSpan="true"
        :height=400 gridLines="Both" :enableHover=false :allowSelection=false :allowPaging='true'
        :pageSettings='pageSettings' clipMode='EllipsisWithTooltip'>
        <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>
</div>
</template>
<script>

import { TreeGridComponent, ColumnDirective, ColumnsDirective, Freeze, Page } from "@syncfusion/ej2-vue-treegrid";
import { rowSpanData } from "./datasource.js";

export default {
name: "App",
components: {
"ejs-treegrid":TreeGridComponent,
"e-columns":ColumnsDirective,
"e-column":ColumnDirective,
},

  data() {
    return {
      data: rowSpanData,
      pageSettings: { pageSizeMode: 'All', pageSize: 18 },
      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' }
      ],
      personnelColumns: [
        {
          field: 'supervisor',
          headerText: 'Supervisor',
          width: 180,
        },
        { field: 'team', headerText: 'Crew', width: 200 }
      ],
      statusColumns: [
        { field: 'status', headerText: 'Status', width: 180, textAlign: 'Center' }
      ],
      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' }
      ],
      materialsColumns: [
        { field: 'materialUsed', headerText: 'Materials Used', width: 180, textAlign: 'Center' },
        { field: 'materialCost', headerText: 'Material Cost', width: 140, format: 'C2', textAlign: 'Right', enableRowSpan: false }
      ],
      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 }
      ]
    };
  },
  provide: {
    treegrid: [Freeze, Page]
  }
}
</script>

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

The row spanning feature is not compatible with all functionalities available in TreeGrid and offers only limited feature support. The following list outlines the features that are not compatible with row spanning.

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