How to select one child per parent in React
4 Sep 202616 minutes to read
React Tree View allows both single and multiple selections. If your application needs to select one child at a time under one specific parent, refer to the following example. You can achieve this in the nodeSelecting event of the React Tree View by clearing any previously selected sibling before the new selection is applied. The sample below also shows how to reset the selected child and re-select another sibling by holding Ctrl while clicking.
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { TreeViewComponent } from '@syncfusion/ej2-react-navigations';
function App() {
// Self-referential list data source for TreeView component
let localData = [
{ id: 1, name: 'Parent 1', hasChild: true, expanded: true },
{ id: 2, pid: 1, name: 'Child 1' },
{ id: 3, pid: 1, name: 'Child 2' },
{ id: 4, pid: 1, name: 'Child 3' },
{ id: 7, name: 'Parent 2', hasChild: true, expanded: true },
{ id: 8, pid: 7, name: 'Child 1' },
{ id: 9, pid: 7, name: 'Child 2' },
{ id: 10, pid: 7, name: 'Child 3' },
];
let field = { dataSource: localData, id: 'id', parentID: 'pid', text: 'name', hasChildren: 'hasChild' };
let allowMultiSelection = true;
let loadOnDemand = false;
let parent;
let child;
let count = false;
let childCount = false;
let treeObj;
// Triggers when you select any node
function onNodeSelecting(args) {
let id = args.nodeData.parentID;
if (!count) {
parent = id;
count = true;
}
if (!childCount) {
child = args.nodeData.id;
childCount = true;
}
if (id != null && id === parent) {
let element = treeObj.element.querySelector('[data-uid="' + id + '"]');
let liElements = element.querySelectorAll('ul li');
for (let i = 0; i < liElements.length; i++) {
let nodeData = treeObj.getNode(liElements[i]);
if (nodeData.selected && args.action === "select" && child !== args.nodeData.id) {
args.cancel = true;
}
// For unselect the selectedNodes
else if (args.action === "un-select" && child === args.nodeData.id) {
childCount = false;
child = null;
parent = null;
count = false;
}
}
}
else if (id !== parent && id !== null) {
if (args.action == "select") {
args.cancel = true;
}
}
else if (id === null) {
childCount = false;
child = null;
parent = null;
count = false;
}
}
return (<div className='control-pane'>
<div className='control-section'>
<div className='control_wrapper'>
{/* Render TreeView */}
<TreeViewComponent fields={field} loadOnDemand={loadOnDemand} nodeSelecting={onNodeSelecting.bind(this)} allowMultiSelection={allowMultiSelection} ref={(treeview) => { treeObj = treeview; }}/>
</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, NodeSelectEventArgs } from '@syncfusion/ej2-react-navigations';
function App() {
// Self-referential list data source for TreeView component
let localData: { [key: string]: Object }[]= [
{ id: 1, name: 'Parent 1', hasChild: true, expanded: true },
{ id: 2, pid: 1, name: 'Child 1' },
{ id: 3, pid: 1, name: 'Child 2' },
{ id: 4, pid: 1, name: 'Child 3' },
{ id: 7, name: 'Parent 2', hasChild: true, expanded: true },
{ id: 8, pid: 7, name: 'Child 1' },
{ id: 9, pid: 7, name: 'Child 2' },
{ id: 10, pid: 7, name: 'Child 3' },
];
let field: Object = { dataSource: localData, id: 'id', parentID: 'pid', text: 'name', hasChildren: 'hasChild' };
let allowMultiSelection: boolean = true;
let loadOnDemand: boolean = false;
let parent: any; let child: any;
let count: boolean = false;
let childCount: boolean = false;
let treeObj: TreeViewComponent;
// Triggers when you select any node
function onNodeSelecting(args: NodeSelectEventArgs): void {
let id: any = args.nodeData.parentID;
if (!count) {
parent = id;
count = true;
}
if (!childCount){
child = args.nodeData.id;
childCount = true
}
if (id != null && id === parent) {
let element: HTMLElement = treeObj.element.querySelector('[data-uid="' + id + '"]');
let liElements: any = element.querySelectorAll('ul li');
for (let i: number = 0; i < liElements.length; i++) {
let nodeData: any = treeObj.getNode(liElements[i]);
if (nodeData.selected && args.action === "select" && child !== args.nodeData.id) {
args.cancel = true;
}
// For unselect the selectedNodes
else if (args.action === "un-select" && child === args.nodeData.id) {
childCount = false;
child = null;
parent = null;
count = false;
}
}
} else if (id !== parent && id !== null) {
if(args.action == "select"){
args.cancel = true
}
} else if (id === null){
childCount = false;
child = null;
parent = null;
count = false
}
}
return (
<div className = 'control-pane'>
<div className='control-section'>
<div className='control_wrapper'>
{/* Render TreeView */}
<TreeViewComponent fields={field} loadOnDemand={loadOnDemand} nodeSelecting={onNodeSelecting.bind(this)} allowMultiSelection={allowMultiSelection} ref={(treeview) => { treeObj = treeview as TreeViewComponent; }}/>
</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/34.2.2/ej2-base/styles/tailwind3.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-react-navigations/styles/tailwind3.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></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;
}