Search results

Hierarchical Binding

The Grid allows display of table data in a hierarchical structure to visualize relations between parent and child records. This feature is enabled by defining the childGrid and childGrid.queryString. The childGrid describes the options of grid and the childGrid.queryString describes the relation between parent and child grids.

To use hierarchical binding, inject the DetailRow module in the grid.

Source
Preview
index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GridComponent, Inject, ColumnsDirective, ColumnDirective, DetailRow, GridModel } from '@syncfusion/ej2-react-grids';
import { data, employeeData } from './datasource';

class App extends React.Component<{}, {}>{

    public childGridOptions : GridModel = {
        dataSource: data,
        queryString: 'EmployeeID',
        columns: [
            { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 120 },
            { field: 'CustomerID', headerText: 'Customer ID', width: 150 },
            { field: 'ShipCity', headerText: 'Ship City', width: 150 },
            { field: 'ShipName', headerText: 'Ship Name', width: 150 }
        ],
    };

    render(){
        return <GridComponent  dataSource={employeeData} childGrid={this.childGridOptions} height={315}>
                  <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right"></ColumnDirective>
                    <ColumnDirective field='FirstName' headerText='First Name' width='150'></ColumnDirective>
                    <ColumnDirective field='City' headerText='City' width='150'></ColumnDirective>
                    <ColumnDirective field='Country' headerText='Country' width='150'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[DetailRow]}/>
            </GridComponent >
        }
};
ReactDOM.render(<App />, document.getElementById('grid'));
  • Grid supports n levels of child grids.
  • Hierarchical Binding is not supported when DetailTemplate is enabled.

ExpandAll by external Button

By default, grid renders in collapsed state. You can expand all child grid rows by invoking the expandAll method and collapse all grid rows by invoking the collapseAll through an external button.

Source
Preview
index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { GridComponent, Inject, ColumnsDirective, ColumnDirective, DetailRow, GridModel } from '@syncfusion/ej2-react-grids';
import { data, employeeData } from './datasource';

class App extends React.Component<{}, {}>{

    public childGridOptions : GridModel = {
        dataSource: data,
        queryString: 'EmployeeID',
        columns: [
            { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 120 },
            { field: 'CustomerID', headerText: 'Customer ID', width: 150 },
            { field: 'ShipCity', headerText: 'Ship City', width: 150 },
            { field: 'ShipName', headerText: 'Ship Name', width: 150 }
        ],
    };

public collapseHandler(){
    this.grid.detailRowModule.collapseAll();
}

public expandHandler(){
this.grid.detailRowModule.expandAll();
}
private grid: Grid;
public inputStyle : Object = {width:'200px', display: 'inline-block'};
    render(){
        return (<div>
        <ButtonComponent onClick= { this.expandHandler.bind(this)}>ExpandAll</ButtonComponent>
        <ButtonComponent onClick= { this.collapseHandler.bind(this)}>CollapseAll</ButtonComponent>
        <GridComponent  dataSource={employeeData} childGrid={this.childGridOptions} height={265} ref={g => this.grid = g}>
                  <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right"></ColumnDirective>
                    <ColumnDirective field='FirstName' headerText='First Name' width='150'></ColumnDirective>
                    <ColumnDirective field='City' headerText='City' width='150'></ColumnDirective>
                    <ColumnDirective field='Country' headerText='Country' width='150'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[DetailRow]}/>
            </GridComponent></div>)
        }
};
ReactDOM.render(<App />, document.getElementById('grid'));

Expand Child Grid Initially

You can expand a particular Child Grid at initial rendering by invoking the expand method in dataBound event.

Source
Preview
index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GridComponent, Inject, ColumnsDirective, ColumnDirective, DetailRow, GridModel } from '@syncfusion/ej2-react-grids';
import { data, employeeData } from './datasource';

class App extends React.Component<{}, {}>{

    public childGridOptions : GridModel = {
        dataSource: data,
        queryString: 'EmployeeID',
        columns: [
            { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 120 },
            { field: 'CustomerID', headerText: 'Customer ID', width: 150 },
            { field: 'ShipCity', headerText: 'Ship City', width: 150 },
            { field: 'ShipName', headerText: 'Ship Name', width: 150 }
        ],
    };

    public OnDataBound() {
        this.detailRowModule.expand(1); //Initial expand 1 chid Grid.
    }

    render(){
        return <GridComponent  dataSource={employeeData} childGrid={this.childGridOptions} height={315} dataBound={this.OnDataBound}>
                  <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right"></ColumnDirective>
                    <ColumnDirective field='FirstName' headerText='First Name' width='150'></ColumnDirective>
                    <ColumnDirective field='City' headerText='City' width='150'></ColumnDirective>
                    <ColumnDirective field='Country' headerText='Country' width='150'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[DetailRow]}/>
            </GridComponent >
        }
};
ReactDOM.render(<App />, document.getElementById('grid'));

Dynamically Load Child Grid Data

You can Dynamically load child Grid dataSource by using detailDataBound event. This detailDataBound event triggers while expand the child Grid at first time.

Source
Preview
index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GridComponent, Inject, ColumnsDirective, ColumnDirective, DetailRow, GridModel } from '@syncfusion/ej2-react-grids';
import { data, employeeData } from './datasource';

class App extends React.Component<{}, {}>{

    public childGridOptions : GridModel = {
        queryString: 'EmployeeID',
        columns: [
            { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 120 },
            { field: 'CustomerID', headerText: 'Customer ID', width: 150 },
            { field: 'ShipCity', headerText: 'Ship City', width: 150 },
            { field: 'ShipName', headerText: 'Ship Name', width: 150 }
        ],
    };

    public onLoad() {
        this.childGrid.dataSource = data; //Assing data source for child grid.
    }

    render(){
        return <GridComponent dataSource={employeeData} childGrid={this.childGridOptions} height={315} load={this.onLoad}>
                  <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right"></ColumnDirective>
                    <ColumnDirective field='FirstName' headerText='First Name' width='150'></ColumnDirective>
                    <ColumnDirective field='City' headerText='City' width='150'></ColumnDirective>
                    <ColumnDirective field='Country' headerText='Country' width='150'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[DetailRow]}/>
            </GridComponent >
        }
};
ReactDOM.render(<App />, document.getElementById('grid'));

Bind hierarchy grid with different field

By default, Parent and child grid relation will be maintained by queryString property. We should use the same field name to map both parent and child grid. To achieve parent and child relation with different fields, we need to change the mapping value in the child grid load event.

In the below sample, we have bound the child and parent grid with different fields. Parent grid field name as EmployeeID and the child grid field name as ID. We need to define the mapping value of parentKeyFieldValue from the parent row data in the child grid load event.

Source
Preview
index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GridComponent, Inject, ColumnsDirective, ColumnDirective, DetailRow, GridModel } from '@syncfusion/ej2-react-grids';
import { data, employeeData, childdata } from './datasource';

class App extends React.Component<{}, {}>{

    public childGridOptions : GridModel = {
        queryString: 'ID',
        dataSource: childdata,
        columns: [
            { field: 'ID', headerText: 'Order ID', textAlign: 'Right', width: 120 },
            { field: 'CustomerID', headerText: 'Customer ID', width: 150 },
            { field: 'ShipCity', headerText: 'Ship City', width: 150 },
            { field: 'ShipName', headerText: 'Ship Name', width: 150 }
        ],
        load: function(){
         this.parentDetails.parentKeyFieldValue = this.parentDetails.parentRowData['EmployeeID'];
        }
    };

    render(){
        return <GridComponent dataSource={employeeData} childGrid={this.childGridOptions} height={315}>
                  <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right"></ColumnDirective>
                    <ColumnDirective field='FirstName' headerText='First Name' width='150'></ColumnDirective>
                    <ColumnDirective field='City' headerText='City' width='150'></ColumnDirective>
                    <ColumnDirective field='Country' headerText='Country' width='150'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[DetailRow]}/>
            </GridComponent >
        }
};
ReactDOM.render(<App />, document.getElementById('grid'));

Adding Record in ChildGrid

Parent and child grid are related by queryString field value. To maintain this relation in newly added record, You need to set value for queryString field in the added data by the actionBegin event.

In the below demo, EmployeeID field relates the parent and child grids. To add a new record in child grid, We have to set the EmployeeID field with parent record’s queryString field value in the actionBegin event.

Source
Preview
index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GridComponent, Inject, ColumnsDirective, ColumnDirective, DetailRow, Edit, Toolbar, AddEventArgs, GridModel } from '@syncfusion/ej2-react-grids';
import { data, employeeData } from './datasource';

class App extends React.Component<{}, {}>{

    public childGridOptions : GridModel = {
        dataSource: data,
        queryString: 'EmployeeID',
        toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
        editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true },
        columns: [
            { field: 'OrderID', headerText: 'Order ID', isPrimaryKey:true, textAlign: 'Right', width: 120 },
            { field: 'EmployeeID', headerText: 'Employee ID', textAlign: 'Right', allowEditing:false, width: 120 },
            { field: 'ShipCity', headerText: 'Ship City', width: 150 },
            { field: 'ShipName', headerText: 'Ship Name', width: 150 }
        ],
        actionBegin: function(args: AddEventArgs) {
        if (args.requestType === "add") {
        // `parentKeyFieldValue` refers to the queryString field value of the parent record.
       args.data.EmployeeID = this.parentDetails.parentKeyFieldValue;
           }
        }
    };

    render(){
        return <GridComponent dataSource={employeeData} childGrid={this.childGridOptions} height={315}>
                  <ColumnsDirective>
                    <ColumnDirective field='EmployeeID' headerText='Employee ID' width='120' textAlign="Right"></ColumnDirective>
                    <ColumnDirective field='FirstName' headerText='First Name' width='150'></ColumnDirective>
                    <ColumnDirective field='City' headerText='City' width='150'></ColumnDirective>
                    <ColumnDirective field='Country' headerText='Country' width='150'></ColumnDirective>
                </ColumnsDirective>
                <Inject services={[DetailRow, Edit, Toolbar]}/>
            </GridComponent >
        }
};
ReactDOM.render(<App />, document.getElementById('grid'));