Virtual scroll in React TreeGrid

8 Oct 202518 minutes to read

TreeGrid loads large data sets without performance degradation. To enable virtualization, inject VirtualScrollService in the TreeGrid.

Row virtualization

Row virtualization loads and renders only the rows within the content viewport. It serves as an alternative to paging; rows are appended during vertical scrolling. To set up row virtualization, set enableVirtualization to true and define the content height using the height property.

The number of records displayed is determined by the content area height, and a buffer of records is maintained in the TreeGrid content in addition to the visible rows.

Expand and collapse state of any child record is persisted.

import { TreeGridComponent, ColumnsDirective, ColumnDirective, Inject, VirtualScroll } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';

import { dataSource, virtualData } from './datasource';
function App() {
    dataSource();
    return <TreeGridComponent dataSource={virtualData} childMapping='Crew' enableVirtualization={true} treeColumnIndex={1} height='291'>
        <ColumnsDirective>
            <ColumnDirective field='TaskID' headerText='Player Jersey' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD1' headerText='Player Name' width='120'></ColumnDirective>
            <ColumnDirective field='FIELD2' headerText='Year' width='100' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD3' headerText='Stint' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD4' headerText='TMID' width='120' textAlign='Right'></ColumnDirective>
            </ColumnsDirective>
            <Inject services={[VirtualScroll]}/>
    </TreeGridComponent>;
}
;
export default App;
import { TreeGridComponent, ColumnsDirective, ColumnDirective, Inject, VirtualScroll } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';

import { dataSource, virtualData } from './datasource';

function App() {
    dataSource();
    return <TreeGridComponent dataSource={virtualData} childMapping = 'Crew' enableVirtualization={true} treeColumnIndex={1} height='291'>
        <ColumnsDirective>
            <ColumnDirective field='TaskID' headerText='Player Jersey' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD1' headerText='Player Name' width='120'></ColumnDirective>
            <ColumnDirective field='FIELD2' headerText='Year' width='100' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD3' headerText='Stint' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD4' headerText='TMID' width='120' textAlign='Right'></ColumnDirective>
            </ColumnsDirective>
            <Inject services={[VirtualScroll]} />
    </TreeGridComponent>
};
export default App;

Limitations

  • Row virtual scrolling is not compatible with the following features:
    1. Batch editing
    2. Checkbox selection
    3. Detail template
    4. Row template
    5. Rowspan
    6. Autofill
  • A static height must be set for the component or its parent container when using row virtualization. A 100% height works only if the component height is set to 100% and its parent container has a static height.
  • When row virtual scrolling is active, copy-paste and drag-and-drop operations apply only to the data items visible in the current viewport.
  • Cell-based selection is not supported with row virtual scrolling.
  • Variable row heights caused by template columns are not supported when template heights differ per row.
  • Due to browser element height limits, the maximum number of records loaded is constrained by browser capabilities.
  • TreeGrid content height is calculated using row height and total record count; therefore, features that change row height (such as text wrapping) are not supported.
  • To increase row height to accommodate content while keeping a consistent height across rows, specify a row height as shown below:
    .e-treegrid .e-row {
    height: 2em;
    }

Column virtualization

Column virtualization renders only the columns within the current viewport, and other columns are rendered on demand during horizontal scrolling.

To set up column virtualization, set both enableVirtualization and enableColumnVirtualization to true.

import { TreeGridComponent, ColumnsDirective, ColumnDirective, Inject, VirtualScroll } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';

import { dataSource, virtualData } from './datasource';
function App() {
    dataSource();
    return <TreeGridComponent dataSource={virtualData} childMapping='Crew' enableVirtualization={true} enableColumnVirtualization={true} treeColumnIndex={1} height='291'>
        <ColumnsDirective>
            <ColumnDirective field='TaskID' headerText='Player Jersey' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD1' headerText='Player Name' width='120'></ColumnDirective>
            <ColumnDirective field='FIELD2' headerText='Year' width='100' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD3' headerText='Stint' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD4' headerText='TMID' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD5' headerText='LGID' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD6' headerText='GP' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD7' headerText='GS' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD8' headerText='Minutes' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD9' headerText='Points' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD10' headerText='oRebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD11' headerText='dRebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD12' headerText='Rebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD13' headerText='Assists' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD14' headerText='Steals' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD15' headerText='Blocks' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD16' headerText='Turnovers' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD17' headerText='PF' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD18' headerText='fgAttempted' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD19' headerText='ftAttempted' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD20' headerText='ThreeAttempted' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD21' headerText='ThreeMade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD22' headerText='PostGP' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD23' headerText='ftMade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD24' headerText='fgMade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD25' headerText='ffmade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD26' headerText='PostGS' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD27' headerText='PostMinutes' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD28' headerText='PostPoints' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD29' headerText='PostoRebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD30' headerText='PostdRebounds' width='120' textAlign='Right'></ColumnDirective>
            </ColumnsDirective>
            <Inject services={[VirtualScroll]}/>
    </TreeGridComponent>;
}
;
export default App;
import { TreeGridComponent, ColumnsDirective, ColumnDirective, Inject, VirtualScroll } from '@syncfusion/ej2-react-treegrid';
import * as React from 'react';

import { dataSource, virtualData } from './datasource';

function App() {
    dataSource();
    return <TreeGridComponent dataSource={virtualData} childMapping = 'Crew' enableVirtualization={true} enableColumnVirtualization={true} treeColumnIndex={1} height='291'>
        <ColumnsDirective>
            <ColumnDirective field='TaskID' headerText='Player Jersey' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD1' headerText='Player Name' width='120'></ColumnDirective>
            <ColumnDirective field='FIELD2' headerText='Year' width='100' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD3' headerText='Stint' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD4' headerText='TMID' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD5' headerText='LGID' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD6' headerText='GP' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD7' headerText='GS' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD8' headerText='Minutes' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD9' headerText='Points' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD10' headerText='oRebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD11' headerText='dRebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD12' headerText='Rebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD13' headerText='Assists' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD14' headerText='Steals' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD15' headerText='Blocks' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD16' headerText='Turnovers' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD17' headerText='PF' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD18' headerText='fgAttempted' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD19' headerText='ftAttempted' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD20' headerText='ThreeAttempted' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD21' headerText='ThreeMade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD22' headerText='PostGP' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD23' headerText='ftMade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD24' headerText='fgMade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD25' headerText='ffmade' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD26' headerText='PostGS' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD27' headerText='PostMinutes' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD28' headerText='PostPoints' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD29' headerText='PostoRebounds' width='120' textAlign='Right'></ColumnDirective>
            <ColumnDirective field='FIELD30' headerText='PostdRebounds' width='120' textAlign='Right'></ColumnDirective>
            </ColumnsDirective>
            <Inject services={[VirtualScroll]} />
    </TreeGridComponent>
};
export default App;

Column’s width is required for column virtualization. If a column width is not defined, TreeGrid considers 200px.

Limitations

  • With column virtual scrolling, column width must be in pixels; percentage values are not supported.
  • Selected column details are retained only within the viewport. When the next set of columns loads, selection for previously visible columns is cleared.
  • Cell selection is not supported with column virtual scrolling.
  • The keyboard shortcuts Ctrl + Home and Ctrl + End are not supported with column virtual scrolling.
  • The following features are compatible with column virtualization and operate only within the viewport:
    1. Column resizing
    2. Column reordering
    3. Auto-fit
    4. Print
    5. Clipboard
    6. Column menu — Column chooser, AutofitAll
  • Column virtual scrolling is not compatible with the following features:
    1. Colspan
    2. Batch editing
    3. Checkbox selection
    4. Column with infinite scrolling
    5. Stacked header
    6. Row template
    7. Detail template
    8. Autofill
    9. Column chooser

Refer to the React Tree Grid feature tour page for highlights. Explore the React Tree Grid example to learn how to present and manipulate data.