Sorting TreeView level wise in React TreeView component

28 Feb 202518 minutes to read

You can sort the TreeView nodes based on their level. When using the sortOrder property, the whole TreeView is sorted. When you sort a particular level, you can use the following code sample. The following code sample demonstrates how to sort the parent node alone in TreeView.

import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { TreeViewComponent } from '@syncfusion/ej2-react-navigations';
import { enableRipple } from '@syncfusion/ej2-base';
import { DataManager, Query } from '@syncfusion/ej2-data';
enableRipple(true);
function App() {
    // Data source for TreeView component
    let Countries = [
        { id: 1, name: 'India', hasChild: true },
        { id: 2, pid: 1, name: 'Assam' },
        { id: 3, pid: 1, name: 'Bihar' },
        { id: 4, pid: 1, name: 'Tamil Nadu' },
        { id: 6, pid: 1, name: 'Punjab' },
        { id: 7, name: 'Brazil', hasChild: true },
        { id: 8, pid: 7, name: 'Paraná' },
        { id: 9, pid: 7, name: 'Ceará' },
        { id: 10, pid: 7, name: 'Acre' },
        { id: 11, name: 'France', hasChild: true },
        { id: 12, pid: 11, name: 'Pays de la Loire' },
        { id: 13, pid: 11, name: 'Aquitaine' },
        { id: 14, pid: 11, name: 'Brittany' },
        { id: 15, pid: 11, name: 'Lorraine' },
        { id: 16, name: 'Australia', hasChild: true },
        { id: 17, pid: 16, name: 'New South Wales' },
        { id: 18, pid: 16, name: 'Victoria' },
        { id: 19, pid: 16, name: 'South Australia' },
        { id: 20, pid: 16, name: 'Western Australia' },
        { id: 21, name: 'China', hasChild: true },
        { id: 22, pid: 21, name: 'Guangzhou' },
        { id: 23, pid: 21, name: 'Shanghai' },
        { id: 24, pid: 21, name: 'Beijing' },
        { id: 25, pid: 21, name: 'Shantou' }
    ];
    let field = { dataSource: Countries, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' };
    let newData;
    let treeObj;
    function onNodeExpand(args) {
        if (args.isInteracted && args.node.querySelector('li') === null) {
            let id = parseInt(args.node.getAttribute("data-uid"));
            let childData = new DataManager(newData).executeLocal(new Query().where(treeObj.fields.parentID, 'equal', id, false));
            treeObj.addNodes(childData, args.node, null);
        }
    }
    function onCreate() {
        newData = treeObj.fields.dataSource;
        // Selects the first level nodes alone
        let resultData = new DataManager(treeObj.getTreeData()).executeLocal(new Query().where(treeObj.fields.parentID, 'equal', null, false));
        let name = [];
        for (let i = 0; i < resultData.length; i++) {
            name.push(resultData[i][treeObj.fields.text]);
        }
        name.sort();
        let arr = [];
        for (let j = 0; j < name.length; j++) {
            let sortedData = new DataManager(treeObj.getTreeData()).executeLocal(new Query().where(treeObj.fields.text, 'equal', name[j], false));
            let childData = new DataManager(newData).executeLocal(new Query().where(treeObj.fields.parentID, 'equal', parseInt(sortedData[0][treeObj.fields.id]), false));
            arr.push(sortedData[0]);
        }
        // Renders treeview with sorted Nodes
        changeDataSource(arr);
        treeObj.dataBind();
    }
    function changeDataSource(data) {
        treeObj.fields = {
            dataSource: data, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild'
        };
    }
    return (<div className='control-pane'>
        <div className='control-section'>
        <div className='control_wrapper'>
            {/* Render TreeView */}
            <TreeViewComponent fields={field} ref={(treeview) => { treeObj = treeview; }} created={onCreate.bind(this)} nodeExpanding={onNodeExpand.bind(this)}/>
        </div>
        </div>
      </div>);
}
export default App;
ReactDOM.render(<App />, document.getElementById('sample'));
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import {TreeViewComponent, NodeExpandEventArgs } from '@syncfusion/ej2-react-navigations';
import {enableRipple} from '@syncfusion/ej2-base';
import { DataManager, Query } from '@syncfusion/ej2-data';
enableRipple(true);

function App() {

   // Data source for TreeView component
   let Countries: { [key: string]: Object }[]= [
    { id: 1, name: 'India', hasChild: true },
    { id: 2, pid: 1, name: 'Assam' },
    { id: 3, pid: 1, name: 'Bihar' },
    { id: 4, pid: 1, name: 'Tamil Nadu' },
    { id: 6, pid: 1, name: 'Punjab' },
    { id: 7, name: 'Brazil', hasChild: true },
    { id: 8, pid: 7, name: 'Paraná' },
    { id: 9, pid: 7, name: 'Ceará' },
    { id: 10, pid: 7, name: 'Acre' },
    { id: 11, name: 'France', hasChild: true },
    { id: 12, pid: 11, name: 'Pays de la Loire' },
    { id: 13, pid: 11, name: 'Aquitaine' },
    { id: 14, pid: 11, name: 'Brittany' },
    { id: 15, pid: 11, name: 'Lorraine' },
    { id: 16, name: 'Australia', hasChild: true },
    { id: 17, pid: 16, name: 'New South Wales' },
    { id: 18, pid: 16, name: 'Victoria' },
    { id: 19, pid: 16, name: 'South Australia' },
    { id: 20, pid: 16, name: 'Western Australia' },
    { id: 21, name: 'China', hasChild: true },
    { id: 22, pid: 21, name: 'Guangzhou' },
    { id: 23, pid: 21, name: 'Shanghai' },
    { id: 24, pid: 21, name: 'Beijing' },
    { id: 25, pid: 21, name: 'Shantou' }
   ]

    let field:Object ={  dataSource: Countries, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' };
    let newData: any;
    let treeObj: TreeViewComponent;

    function onNodeExpand(args: NodeExpandEventArgs): void {
        if (args.isInteracted && args.node.querySelector('li') === null){
            let id: any = parseInt(args.node.getAttribute("data-uid"));
            let childData: any =  new DataManager(newData).executeLocal(new Query().where(treeObj.fields.parentID, 'equal', id, false));
            treeObj.addNodes(childData, args.node,null)
        }
    }

    function onCreate(){
        newData = treeObj.fields.dataSource;
        // Selects the first level nodes alone
        let resultData = new DataManager(treeObj.getTreeData()).executeLocal(new Query().where(treeObj.fields.parentID, 'equal', null, false));
        let name = [];
        for (let i = 0; i < resultData.length; i++){
            name.push(resultData[i][treeObj.fields.text]);
        }
        name.sort();
        let arr = [];
        for (let j = 0; j < name.length; j++) {
            let sortedData = new DataManager(treeObj.getTreeData()).executeLocal(new Query().where(treeObj.fields.text, 'equal', name[j], false));
            let childData =  new DataManager(newData).executeLocal(new Query().where(treeObj.fields.parentID, 'equal', parseInt(sortedData[0][treeObj.fields.id]), false));
            arr.push(sortedData[0]);
        }
        // Renders treeview with sorted Nodes
        changeDataSource(arr);
        treeObj.dataBind();
    }

     function changeDataSource(data: any){
        treeObj.fields = {
            dataSource: data, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild'
        }
    }
    return (
      <div className = 'control-pane'>
        <div className='control-section'>
        <div className='control_wrapper'>
            {/* Render TreeView */}
            <TreeViewComponent fields={field} ref={(treeview) => { treeObj = treeview as TreeViewComponent; }} created={onCreate.bind(this)} nodeExpanding={onNodeExpand.bind(this)} />
        </div>
        </div>
      </div>
    )
}
export default App;
ReactDOM.render(<App />, document.getElementById('sample'));
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React TreeView</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="style.css" rel="stylesheet"/>
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/29.1.33/ej2-react-navigations/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='treeparent'>
        <div id='sample'>
            <div id='loader'>Loading....</div>
        </div>
    </div>
</body>

</html>
#loader {
    color: #008cff;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
}

#treeparent {
    display: block;
    max-width: 350px;
    max-height: 350px;
    margin: auto;
    overflow: auto;
    border: 1px solid #dddddd;
    border-radius: 3px;
}