Template in React TreeView component

28 Feb 202522 minutes to read

The TreeView component allows you to customize the look of TreeView nodes by using the nodeTemplate property. This property accepts either template string or HTML element ID.

In the following sample, employee information such as employee photo, name, and designation have been included using the nodeTemplate property.

The template expression should be provided inside the ${...} interpolation syntax.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
import { TreeViewComponent } from '@syncfusion/ej2-react-navigations';
function App() {
    let employees = [
        { id: 1, name: 'Steven Buchanan', eimg: '10', job: 'CEO', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Laura Callahan', eimg: '2', job: 'Product Manager', hasChild: true },
        { id: 3, pid: 2, name: 'Andrew Fuller', eimg: '7', job: 'Team Lead', hasChild: true },
        { id: 4, pid: 3, name: 'Anne Dodsworth', eimg: '1', job: 'Developer' },
        { id: 5, pid: 1, name: 'Nancy Davolio', eimg: '4', job: 'Product Manager', hasChild: true },
        { id: 6, pid: 5, name: 'Michael Suyama', eimg: '9', job: 'Team Lead', hasChild: true },
        { id: 7, pid: 6, name: 'Robert King', eimg: '8', job: 'Developer ' },
        { id: 8, pid: 7, name: 'Margaret Peacock', eimg: '6', job: 'Developer' },
        { id: 9, pid: 1, name: 'Janet Leverling', eimg: '3', job: 'HR' },
    ];
    let fields = { dataSource: employees, id: 'id', parentID: 'pid', text: 'name', hasChildren: 'hasChild' };
    let cssClass = "custom";
    function nodeTemplate(data) {
        return (<div>
        <img
            className="eimage"
            src={`https://ej2.syncfusion.com/demos/src/treeview/images/employees/${data.eimg}.png`}
            alt="${data.eimg}"
          />
        <div className='ename'>{data.name}</div>
        <div className='ejob'>{data.job}</div>
      </div>);
    }
    return (
    // specifies the tag for render the TreeView component
    <TreeViewComponent fields={fields} cssClass={cssClass} nodeTemplate={nodeTemplate}/>);
}
export default App;
ReactDOM.render(<App />, document.getElementById('sample'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {enableRipple} from '@syncfusion/ej2-base';
enableRipple(true);
import {TreeViewComponent} from '@syncfusion/ej2-react-navigations';

function App() {

let employees: { [key: string]: Object }[] = [
   { id: 1, name: 'Steven Buchanan', eimg: '10', job: 'CEO', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Laura Callahan', eimg: '2', job: 'Product Manager', hasChild: true },
        { id: 3, pid: 2, name: 'Andrew Fuller', eimg: '7', job: 'Team Lead', hasChild: true },
        { id: 4, pid: 3, name: 'Anne Dodsworth', eimg: '1', job: 'Developer' },
        { id: 5, pid: 1, name: 'Nancy Davolio', eimg: '4', job: 'Product Manager', hasChild: true },
        { id: 6, pid: 5, name: 'Michael Suyama', eimg: '9', job: 'Team Lead', hasChild: true },
        { id: 7, pid: 6, name: 'Robert King', eimg: '8', job: 'Developer ' },
        { id: 8, pid: 7, name: 'Margaret Peacock', eimg: '6', job: 'Developer' },
        { id: 9, pid: 1, name: 'Janet Leverling', eimg: '3', job: 'HR' },
];
let fields: Object = { dataSource: employees,  id: 'id', parentID: 'pid', text: 'name', hasChildren: 'hasChild' };
let cssClass:string = "custom";
function nodeTemplate(data:any): JSX.Element {
    return (
      <div>
        <img className='eimage' src={`https://ej2.syncfusion.com/demos/src/treeview/images/employees/${data.eimg}.png`} alt='${data.eimg}'/>
        <div className='ename'>{data.name}</div>
        <div className='ejob'>{data.job}</div>
      </div>
        )
    }
  return (
      // specifies the tag for render the TreeView component
      <TreeViewComponent fields={fields} cssClass={cssClass} nodeTemplate={nodeTemplate}/>
  );
}
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-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;
}

.custom .e-list-item .e-fullrow {
    height: 72px;
}
.custom .e-list-item .e-list-text {
    line-height: normal;
}
.eimage {
    float: left;
    padding: 11px 16px 11px 0;
}
.ename {
    font-size: 16px;
    padding: 14px 0 0;
}
.ejob {
    font-size: 14px;
    opacity: .87;
}

Stateless template

For specific needs of the application, users don’t want to re-render the TreeView component during state updates. This can be achieved using the statelessTemplates property. It specifies the array of template names where the state value updates need to be ignored. It will increase the performance of the components if users prevent state updates for the templates that are not required.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { useState } from 'react';
import { TreeViewComponent } from '@syncfusion/ej2-react-navigations';

function App() {
  const [selectedItem, setSlectedItem] = useState();
  let templateData = [
    { id: 1, name: "Favorites", hasChild: true },
    { id: 2, pid: 1, name: "Sales Reports", count: "4" },
    { id: 3, pid: 1, name: "Sent Items" },
    { id: 4, pid: 1, name: "Marketing Reports ", count: "6" },
    { id: 5, name: "My Folder", hasChild: true, "expanded": true },
    { id: 6, pid: 5, name: "Inbox", "selected": true, count: "20" },
    { id: 7, pid: 5, name: "Drafts", count: "5" },
    { id: 8, pid: 5, name: "Deleted Items" },
    { id: 9, pid: 5, name: "Sent Items" },
    { id: 10, pid: 5, name: "Sales Reports", count: "4" },
    { id: 11, pid: 5, name: "Marketing Reports", count: "6" },
    { id: 12, pid: 5, name: "Outbox" }
  ];
  let fields = { dataSource: templateData, id: 'id', parentID: 'pid', text: 'name', hasChildren: 'hasChild' };
  let cssClass = "custom";
  function nodeTemplate(data) {
    return (<div>
      <div className="treeviewdiv">
        <div className="textcontent">
          <span className="treeName">{data.name}</span>
        </div>
        {data.count && (
          <div className="countcontainer">
            <span className="treeCount e-badge e-badge-primary">
              {data.count}
            </span>
          </div>
        )}
      </div>
    </div>);
  }
  return (
    <div>
      <TreeViewComponent 
        cssClass={cssClass} 
        fields={fields} 
        nodeTemplate={nodeTemplate} 
        nodeSelected={(args) => setSlectedItem(args.nodeData)} 
        statelessTemplates={['nodeTemplate']} 
      />
        <pre>Node name: {selectedItem?.text}</pre>
    </div>
  );
}
export default App;
ReactDOM.render(<App />, document.getElementById('sample'));
import * as React from 'react';
import { useState } from 'react';
import * as ReactDOM from 'react-dom';
import { TreeViewComponent } from '@syncfusion/ej2-react-navigations';

function App() {
  const [selectedItem, setSelectedItem] = React.useState<any>(undefined);
  let templateData: { [key: string]: Object }[] = [
    { id: 1, name: "Favorites", hasChild: true },
    { id: 2, pid: 1, name: "Sales Reports", count: "4" },
    { id: 3, pid: 1, name: "Sent Items" },
    { id: 4, pid: 1, name: "Marketing Reports ", count: "6" },
    { id: 5, name: "My Folder", hasChild: true, "expanded": true },
    { id: 6, pid: 5, name: "Inbox", "selected": true, count: "20" },
    { id: 7, pid: 5, name: "Drafts", count: "5" },
    { id: 8, pid: 5, name: "Deleted Items" },
    { id: 9, pid: 5, name: "Sent Items" },
    { id: 10, pid: 5, name: "Sales Reports", count: "4" },
    { id: 11, pid: 5, name: "Marketing Reports", count: "6" },
    { id: 12, pid: 5, name: "Outbox" }
  ];
  let fields: Object = { dataSource: templateData, id: 'id', parentID: 'pid', text: 'name', hasChildren: 'hasChild' };
  let cssClass:string = "custom";
  function nodeTemplate(data: any): JSX.Element {
    return (
      <div>
        <div className="treeviewdiv">
          <div className="textcontent">
            <span className="treeName">{data.name}</span>
          </div>
          {data.count && (
            <div className="countcontainer">
              <span className="treeCount e-badge e-badge-primary">
                {data.count}
              </span>
            </div>
          )}
        </div>
      </div>
    )
  }
  return (
    <div>
      <TreeViewComponent 
        cssClass={cssClass} 
        fields={fields} 
        nodeTemplate={nodeTemplate} 
        nodeSelected={(args: any) => setSelectedItem(args.nodeData)} 
        statelessTemplates={['nodeTemplate']} 
      />
      <pre>Node name: {selectedItem?.text}</pre>
    </div>

  );
}
export default App;
ReactDOM.render(<App />, document.getElementById('sample'));
#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;
}

.custom .e-list-text {
  width: 100%;
}

.custom .textcontent {
  float: left;
}

.custom .countcontainer {
  float: right;
  margin-right: 5px !important;
}

.custom.e-interaction.e-fullrow-wrap .e-text-content {
  pointer-events: none;
}
<!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-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>

See Also