
Syncfusion React Dropdown Tree
- 384 installs
- 3 repo stars
- Updated July 28, 2026
- syncfusion/react-ui-components-skills
syncfusion-react-dropdown-tree is a Claude Code skill that helps developers implement Syncfusion's React Dropdown Tree component with correct props, hierarchical data binding, and UI patterns for nested selection control
About
syncfusion-react-dropdown-tree is a component-focused frontend skill from syncfusion/react-ui-components-skills for React developers using Syncfusion controls. The skill guides setup and configuration of the Dropdown Tree component, which combines tree hierarchy navigation with dropdown selection for dense data UIs such as org charts, category pickers, and nested folder selectors. Developers reach for syncfusion-react-dropdown-tree when a React dashboard or form needs multi-level selection without building a custom tree-dropdown from scratch. The catalog entry is minimal, so the skill primarily accelerates Syncfusion-specific API usage during active frontend build work.
- syncfusion-react-dropdown-tree
Syncfusion React Dropdown Tree by the numbers
- 384 all-time installs (skills.sh)
- +22 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,095 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/react-ui-components-skills --skill syncfusion-react-dropdown-treeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 384 |
|---|---|
| repo stars | ★ 3 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/react-ui-components-skills ↗ |
How do you add a Syncfusion dropdown tree in React?
Use syncfusion-react-dropdown-tree for development tasks
Who is it for?
React developers integrating Syncfusion Dropdown Tree for nested category, org, or folder selection UIs.
Skip if: Projects not using Syncfusion React components or needing only flat select menus without tree hierarchy.
When should I use this skill?
A React UI needs a Syncfusion Dropdown Tree with hierarchical options, data binding, or selection behavior.
What you get
A configured Syncfusion Dropdown Tree component with hierarchical data binding in a React application.
- dropdown tree component integration
Files
Implementing Dropdown Tree
The Dropdown Tree component displays hierarchical data in a collapsible tree structure within a dropdown interface. It combines tree navigation with dropdown accessibility, supporting multi-selection via checkboxes, lazy loading for large datasets, comprehensive customization through templates and events, filtering, and full accessibility with RTL and localization support.
When to Use This Skill
Use Dropdown Tree immediately when you need to:
- Display hierarchical data - Show nested categories, organizational structures, file trees, or department hierarchies
- Enable multi-selection - Allow users to select multiple items with checkbox support or keyboard modifiers
- Support lazy loading - Optimize performance with large datasets by loading children on demand
- Customize display - Use templates to format items, headers, footers, selected values, or error states
- Implement filtering - Enable search functionality with configurable filter types (StartsWith, EndsWith, Contains)
- Ensure accessibility - Provide WAI-ARIA compliance, keyboard navigation, and screen reader support
- Support multiple languages - Localize UI with customizable keys and RTL support
- Bind remote data - Integrate with OData, OData V4, Web APIs, or other remote data services
- Handle complex selection logic - Use events, auto-check hierarchy, or selective node disabling
Component Overview
The Dropdown Tree features:
- Hierarchical display: Local (hierarchical/self-referential) and remote data sources with flexible binding
- Multi-selection modes: Checkboxes with auto-check, multi-select with Ctrl/Shift keys, single select (default)
- Flexible templates: Item, value, header, footer, noRecords, and actionFailure templates for custom rendering
- Performance optimization: Lazy loading (load-on-demand) for efficient large dataset handling
- Search & filtering: Built-in filter bar with configurable filter types and case sensitivity options
- Comprehensive events: change, select, dataBound, filtering, beforeOpen, focus, keyPress, and popup events
- Accessibility: Full WAI-ARIA (roles, attributes), keyboard navigation, screen reader support, WCAG 2.2 compliance
- Localization: Multi-language support with 4 customizable keys and locale override
- RTL support: Right-to-left layout rendering
- Tree settings: Advanced configuration (expandOn, autoCheck, loadOnDemand, checkDisabledChildren)
- Field mapping: Flexible data structure support (value, text, child, parentValue, expanded, hasChildren, selectable, iconCss, imageUrl, htmlAttributes)
- Display modes: Default, Delimiter, and Custom modes for selected items
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation and package dependencies (npm install command)
- React/TypeScript project setup (Vite and Create React App)
- Basic component implementation and initialization
- CSS imports and theme configuration
- First render and minimal working example
Data Binding
📄 Read: references/data-binding.md
- Local data binding (hierarchical and self-referential structures)
- Remote data with DataManager and various adaptors (OData, OData V4, WebAPI, URL)
- Field mapping for value, text, child, parentValue, expanded, hasChildren
- Load on demand (lazy loading) for large datasets
- Preventing node selection with selectable field
- Query configuration for remote data services
Checkbox & Multi-Selection
📄 Read: references/checkbox-selection.md
- Enabling checkbox support with
showCheckBoxproperty - Multi-selection workflow and accessing selected values
- Auto-check hierarchical behavior (parent-child synchronization)
- Select All feature with customizable
selectAllTextandunSelectAllText - Intermediate checkbox states for partial selection
- CheckDisabledChildren behavior for disabled nodes
Templates
📄 Read: references/templates.md
- Item template for custom list item rendering
- Value template for selected display customization
- Header template for static content above items
- Footer template for static content below items
- NoRecords template for empty state handling
- ActionFailure template for error state handling
- CustomTemplate for multi-select display customization
- Template expression syntax and data access patterns
Multi-Selection & Filtering
📄 Read: references/multi-selection-filtering.md
allowMultiSelectionproperty and Ctrl/Shift keyboard interaction- Display modes: Default, Delimiter, Custom
delimiterCharandmodeconfigurationallowFilteringand filter bar implementation- Filter types: StartsWith, EndsWith, Contains
filterBarPlaceholdercustomizationignoreCaseandignoreAccentoptions
Tree Settings & Configuration
📄 Read: references/tree-settings.md
loadOnDemandfor lazy loading implementationautoCheckfor hierarchical checkbox synchronizationexpandOnbehavior (Auto, Click, DblClick, None)checkDisabledChildrenfor disabled node handling- Tree expansion and collapse control
Field Mapping & Custom Data Structures
📄 Read: references/field-mapping.md
- Core fields: value, text, dataSource, child, parentValue
- Node state fields: expanded, hasChildren, selected, selectable
- Display enhancement fields: iconCss, imageUrl, htmlAttributes
- Query and tableName for remote data
- Nested field mapping for hierarchical data
Advanced Features & API Reference
📄 Read: references/advanced-features.md
- Properties (60+ properties with descriptions and examples)
- Methods (getSelectedNodes, getCheckedNodes, setCheckedNodes, etc.)
- Events (change, select, dataBound, filtering, beforeOpen, focus, keyPress, popup)
- Event arguments (EventArgs structures with property descriptions)
- Styling and CSS customization
- Performance optimization techniques
Accessibility & Localization
📄 Read: references/accessibility-localization.md
- WCAG 2.2 and Section 508 compliance standards
- WAI-ARIA attributes and roles (listbox, treeitem, checkbox, group, etc.)
- Keyboard navigation shortcuts (Alt+Down, Arrow keys, Enter, Space, etc.)
- Screen reader and assistive technology support
- Localization keys (noRecordsTemplate, actionFailureTemplate, overflowCountTemplate, totalCountTemplate)
- Culture customization with locale property
- RTL (Right-to-Left) language support with enableRtl
Quick Start
Basic Dropdown Tree with Hierarchical Data
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import '@syncfusion/ej2-dropdowns/styles/material.css';
function App() {
const data = [
{ id: '1', name: 'Electronics', expanded: true },
{ id: '2', name: 'Laptops', parentId: '1' },
{ id: '3', name: 'Phones', parentId: '1' },
{ id: '4', name: 'Appliances' },
];
return (
<DropDownTreeComponent
id="dropdowntree"
fields={{ dataSource: data, value: 'id', text: 'name', parentValue: 'parentId', hasChildren: 'hasChild' }}
placeholder="Select an item"
/>
);
}
export default App;With Checkboxes and Auto-Check
<DropDownTreeComponent
id="dropdowntree"
fields={{ dataSource: data, value: 'id', text: 'name', parentValue: 'parentId', hasChildren: 'hasChild' }}
showCheckBox={true}
showSelectAll={true}
treeSettings={{ autoCheck: true }}
placeholder="Select items"
/>With Filtering
<DropDownTreeComponent
id="dropdowntree"
fields={{ dataSource: data, value: 'id', text: 'name', parentValue: 'parentId' }}
allowFiltering={true}
filterType="Contains"
filterBarPlaceholder="Search items..."
placeholder="Select an item"
/>With Custom Templates
<DropDownTreeComponent
id="dropdowntree"
fields={{ dataSource: data, value: 'id', text: 'name', parentValue: 'parentId' }}
itemTemplate={(props) => (
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
<span>{props.name}</span>
<small style={{ color: '#999' }}>({props.category})</small>
</div>
)}
valueTemplate={(props) => <span>{props.name}</span>}
placeholder="Select item"
/>Common Patterns
Pattern 1: Self-Referential Data Binding
For flat data structures with parent references:
const data = [
{ id: 1, name: 'Discover Music', hasChild: true, expanded: true },
{ id: 2, pid: 1, name: 'Hot Singles' },
{ id: 3, pid: 1, name: 'Rising Artists' },
{ id: 7, name: 'Sales and Events', hasChild: true },
{ id: 8, pid: 7, name: '100 Albums' },
];
<DropDownTreeComponent
id="dropdowntree"
fields={{
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'pid',
hasChildren: 'hasChild',
}}
/>Pattern 2: Event Handling for Selection Changes
const handleChange = (args) => {
console.log('Old values:', args.oldValue); // string[]
console.log('New values:', args.value); // string[]
console.log('User interaction:', args.isInteracted); // boolean
};
const handleSelect = (args) => {
console.log('Action:', args.action); // 'select' or 'unselect'
console.log('Item data:', args.itemData); // object
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onChange={handleChange}
onSelect={handleSelect}
/>Pattern 3: Multi-Select with Auto-Check
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
showCheckBox={true}
treeSettings={{ autoCheck: true }}
mode="Default"
delimiterChar=", "
placeholder="Select multiple items"
/>Pattern 4: Lazy Loading for Large Datasets
const remoteData = new DataManager({
url: 'url',
adaptor: new UrlAdaptor(),
});
<DropDownTreeComponent
id="dropdowntree"
fields={{ dataSource: remoteData, value: 'id', text: 'name', hasChildren: 'hasChild' }}
treeSettings={{ loadOnDemand: true }}
placeholder="Loading..."
/>Pattern 5: Custom Item Styling with IconCss
const data = [
{ id: 1, name: 'Documents', iconCss: 'e-folder', hasChild: true },
{ id: 2, pid: 1, name: 'Resume.pdf', iconCss: 'e-pdf' },
{ id: 3, pid: 1, name: 'Report.docx', iconCss: 'e-docx' },
];
<DropDownTreeComponent
id="dropdowntree"
fields={{
dataSource: data,
value: 'id',
text: 'name',
iconCss: 'iconCss',
parentValue: 'pid',
hasChildren: 'hasChild',
}}
/>Pattern 6: RTL & Localization Support
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
enableRtl={true}
locale="ar"
placeholder="اختر عنصرا"
/>Key Props Overview
| Property | Type | Description |
|---|---|---|
| Core | ||
id | string | Unique identifier for the component |
fields | FieldsModel | Data source and field mapping configuration |
placeholder | string | Input placeholder text |
enabled | boolean | Enable/disable component (default: true) |
| Selection | ||
showCheckBox | boolean | Enable checkbox multi-selection (default: false) |
showSelectAll | boolean | Show Select All checkbox (default: false) |
selectAllText | string | "Select All" label text |
unSelectAllText | string | "Unselect All" label text |
allowMultiSelection | boolean | Enable multi-selection with Ctrl/Shift keys |
| Templates | ||
itemTemplate | string \ | Function |
valueTemplate | string \ | Function |
headerTemplate | string \ | Function |
footerTemplate | string \ | Function |
noRecordsTemplate | string \ | Function |
actionFailureTemplate | string \ | Function |
| Filtering | ||
allowFiltering | boolean | Enable search/filter bar (default: false) |
filterType | TreeFilterType | Filter type: StartsWith, EndsWith, Contains |
filterBarPlaceholder | string | Filter bar placeholder text |
ignoreCase | boolean | Case-insensitive filtering (default: true) |
ignoreAccent | boolean | Ignore diacritics in filtering |
| Tree Settings | ||
treeSettings | TreeSettingsModel | Tree behavior configuration (autoCheck, loadOnDemand, expandOn) |
| Display | ||
mode | string | Display mode: Default, Delimiter, Custom |
delimiterChar | string | Delimiter for multi-select (default: ", ") |
customTemplate | string | Custom multi-select display template |
| Localization & RTL | ||
locale | string | Culture code (default: "en") |
enableRtl | boolean | Enable Right-to-Left layout |
enablePersistence | boolean | Persist state between page reloads |
| Styling | ||
cssClass | string | CSS class for root and popup |
width | string \ | number |
popupHeight | string \ | number |
htmlAttributes | object | HTML attributes for the component |
Decision Guide
Choosing Data Binding:
- Local hierarchical - Nested JSON objects with
childproperty for small-to-medium datasets - Local self-referential - Flat arrays with
parentValuefield for structured data - Remote with DataManager - OData/Web API for large datasets, dynamic loading, real-time data
Choosing Selection Mode:
- Single select - Default (no checkboxes, no multi-select), read-only visual selection
- Checkboxes -
showCheckBox={true}for explicit multi-selection - Multi-select -
allowMultiSelection={true}for Ctrl/Shift keyboard selection - Auto-check - Combine checkboxes with
treeSettings={{ autoCheck: true }}for hierarchy sync
Choosing Template:
- itemTemplate - Custom formatting per tree item (name + description, icons, badges)
- valueTemplate - Custom display in input field (combined text, formatted values)
- headerTemplate - Static controls above list (instructions, search help, custom controls)
- footerTemplate - Static content below list (count summary, action buttons)
- noRecordsTemplate - Empty state when no data or search yields no results
- actionFailureTemplate - Error message when data fetch fails
When to Use Lazy Loading:
- Large datasets (1000+ items)
- Performance-critical applications
- Data fetched from remote API with pagination
- Hierarchies with many levels
When to Use Filtering:
- Large datasets requiring search
- User-friendly discovery of items
- Reducing cognitive load for selection
Next Steps
- Get started → Read getting-started.md
- Bind data → Read data-binding.md
- Add checkboxes → Read checkbox-selection.md
- Enable filtering → Read multi-selection-filtering.md
- Configure trees → Read tree-settings.md
- Map fields → Read field-mapping.md
- Customize → Read templates.md
- Access APIs → Read advanced-features.md
- Enhance UX → Read accessibility-localization.md
Accessibility & Localization
Table of Contents
- Accessibility Overview
- WCAG Compliance
- WAI-ARIA Attributes
- Keyboard Navigation
- Screen Reader Support
- Localization
- RTL Support
Accessibility Overview
The Dropdown Tree component follows accessibility guidelines to ensure usability for all users, including those with disabilities.
Compliance Standards
| Standard | Support | Notes |
|---|---|---|
| WCAG 2.2 | Partial | Most features meet guidelines |
| Section 508 | Partial | Sufficient for most scenarios |
| Screen Readers | Full | Complete support with ARIA |
| Keyboard Navigation | Full | All features accessible via keyboard |
| Color Contrast | Full | Meets WCAG AA standards |
| Mobile Devices | Full | Touch-friendly interfaces |
| RTL Languages | Full | Full right-to-left support |
WCAG 2.2
Dropdown Tree meets WCAG 2.2 Level AA standards for:
- Perceivable: Content is visible and distinguishable
- Operable: Keyboard accessible, sufficient time for interactions
- Understandable: Clear labels, error prevention
- Robust: Compatible with assistive technologies
Section 508
Complies with U.S. Section 508 accessibility requirements for federal information technology.
WAI-ARIA Attributes
The component uses WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) attributes to communicate with assistive technologies.
ARIA Roles and Attributes
| Attribute | Element | Purpose |
|---|---|---|
role="listbox" | Dropdown container | Identifies list functionality |
role="tree" | Tree structure | Identifies hierarchical tree |
role="treeitem" | Tree node | Identifies individual nodes |
role="group" | Node children | Groups child elements |
role="checkbox" | Checkbox input | Identifies checkbox control |
aria-disabled | Input/Items | Indicates disabled state |
aria-expanded | Expandable items | Shows expanded/collapsed state |
aria-selected | Selected items | Marks selected nodes |
aria-checked | Checkboxes | Indicates checkbox state |
aria-owns | Input | References popup list |
aria-haspopup | Input | Indicates popup availability |
aria-activedescendant | Input | References active list item |
aria-label | Input/Checkboxes | Provides accessible labels |
aria-describedby | Input | Links to description element |
aria-labelledby | Input | References label element |
aria-level | Tree items | Indicates nesting level |
aria-multiselectable | Tree | Indicates multi-select capability |
Using Labels
// Provide accessible label
<div>
<label htmlFor="deptSelect" id="deptLabel">
Select Department:
</label>
<DropDownTreeComponent
id="deptSelect"
aria-labelledby="deptLabel"
fields={{...}}
/>
</div>Using Descriptions
<div>
<DropDownTreeComponent
id="tree"
aria-describedby="treeHelp"
fields={{...}}
/>
<small id="treeHelp">
Select one or more items from the tree. Use arrow keys to navigate.
</small>
</div>Keyboard Navigation
All Dropdown Tree features are accessible via keyboard.
Keyboard Shortcuts
| Key | Action |
|---|---|
| Alt + Down | Open popup |
| Alt + Up | Close popup |
| Escape | Close popup |
| Arrow Up | Select previous item |
| Arrow Down | Select next item |
| Arrow Right | Expand current item |
| Arrow Left | Collapse current item |
| Home | Go to first item |
| End | Go to last item |
| Enter | Select focused item |
| Space | Check/uncheck focused item (with checkboxes) |
| Tab | Move to next control |
| Shift + Tab | Move to previous control |
Keyboard Interaction Example
1. User presses Tab to focus Dropdown Tree input
2. User presses Alt+Down to open popup
3. User presses Arrow Down to navigate items
4. User presses Arrow Right to expand category
5. User presses Space to check item (if checkboxes enabled)
6. User presses Escape to close popup
7. Selection is maintained in input fieldTesting Keyboard Access
// Component properly receives keyboard events
<DropDownTreeComponent
id="tree"
fields={{...}}
// Component handles all keyboard interactions automatically
/>Screen Reader Support
Screen readers (NVDA, JAWS, VoiceOver) announce component state, structure, and changes.
What Screen Readers Announce
- Component type: "List box" or "Tree view"
- Item information: Item text, nesting level, expanded state
- Selection state: "Selected" or "Checked"
- Checkbox status: "Checked", "Unchecked", "Partially checked"
- Interactive instructions: "Press Space to check"
- Error messages: Validation or state change notifications
Best Practices
1. Use Semantic Labels
// Good: Clear label for screen readers
<div>
<label htmlFor="categoryTree">Select Category</label>
<DropDownTreeComponent id="categoryTree" {...props} />
</div>
// Avoid: No label
<DropDownTreeComponent {...props} />2. Provide Help Text
<div>
<DropDownTreeComponent
id="tree"
aria-describedby="help"
{...props}
/>
<p id="help">
Select one item. Use arrow keys to navigate.
</p>
</div>3. Use Clear Item Text
// Good: Descriptive item names
const data = [
{ id: 1, name: 'Electronics - 25 items', parentId: null },
{ id: 2, name: 'Laptops (subcategory)', parentId: 1 },
];
// Less helpful: Vague names
const data = [
{ id: 1, name: 'Item 1', parentId: null },
{ id: 2, name: 'Item 1.1', parentId: 1 },
];Localization
Dropdown Tree supports multiple languages and cultures through localization.
Localization Keys
Default text for English (en culture):
| Key | Default Text | Use Case |
|---|---|---|
noRecordsTemplate | No records found | Displayed when no data matches filter |
actionFailureTemplate | Request failed | Shown on data loading errors |
overflowCountTemplate | +${count} more.. | Shows count of additional selected items |
totalCountTemplate | ${count} selected | Shows total selected items count |
Customize Localization Text
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
// Define custom locale
const customLocale = {
'en': {
'dropdowntree': {
'noRecordsTemplate': 'No items found',
'actionFailureTemplate': 'Connection error. Please try again.',
'overflowCountTemplate': 'and ${count} more',
'totalCountTemplate': '${count} items selected',
}
},
'es': {
'dropdowntree': {
'noRecordsTemplate': 'No hay registros encontrados',
'actionFailureTemplate': 'Error de conexión',
'overflowCountTemplate': 'y ${count} más',
'totalCountTemplate': '${count} elementos seleccionados',
}
}
};
// Register locale
// L10n.load(customLocale); // If using Syncfusion's localization system
<DropDownTreeComponent
fields={{...}}
noRecordsTemplate="No items found"
actionFailureTemplate="Connection error"
/>Multi-Language Support
const [language, setLanguage] = useState('en');
const translations = {
en: {
placeholder: 'Select item',
selectAll: 'Select All',
noRecords: 'No records found',
},
es: {
placeholder: 'Seleccionar elemento',
selectAll: 'Seleccionar todo',
noRecords: 'No se encontraron registros',
},
fr: {
placeholder: 'Sélectionner un élément',
selectAll: 'Sélectionner tout',
noRecords: 'Aucun enregistrement trouvé',
}
};
const current = translations[language];
<DropDownTreeComponent
fields={{...}}
placeholder={current.placeholder}
selectAllText={current.selectAll}
noRecordsTemplate={current.noRecords}
showCheckBox={true}
showSelectAll={true}
/>Common Translations
English (en):
Select Item
Select All / Unselect All
No Records Found
Request Failed
Loading...Spanish (es):
Seleccionar elemento
Seleccionar todo / Deseleccionar todo
No se encontraron registros
Error en la solicitud
Cargando...French (fr):
Sélectionner un élément
Sélectionner tout / Désélectionner tout
Aucun enregistrement trouvé
Erreur de la demande
Chargement...German (de):
Element auswählen
Alles auswählen / Alles abwählen
Keine Datensätze gefunden
Anfragefehler
Wird geladen...Portuguese (pt):
Selecionar elemento
Selecionar tudo / Desselecionar tudo
Nenhum registro encontrado
Erro na solicitação
Carregando...Japanese (ja):
アイテムを選択
すべて選択 / すべての選択を解除
レコードが見つかりません
リクエストエラー
読み込み中...Italian (it):
Seleziona elemento
Seleziona tutto / Deseleziona tutto
Nessun record trovato
Errore della richiesta
Caricamento...Arabic (ar):
اختر عنصراً
تحديد الكل / إلغاء تحديد الكل
لم يتم العثور على سجلات
فشل الطلب
جاري التحميل...Comprehensive Localization Setup
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { L10n } from '@syncfusion/ej2-base';
import React, { useState } from 'react';
// Define comprehensive locale for all languages
L10n.load({
'es': {
'dropdowntree': {
'noRecordsTemplate': 'No se encontraron registros',
'actionFailureTemplate': 'Error al cargar datos',
'overflowCountTemplate': 'y ${count} más',
'totalCountTemplate': '${count} elementos seleccionados'
}
},
'fr': {
'dropdowntree': {
'noRecordsTemplate': 'Aucun enregistrement trouvé',
'actionFailureTemplate': 'Erreur de chargement des données',
'overflowCountTemplate': 'et ${count} plus',
'totalCountTemplate': '${count} éléments sélectionnés'
}
},
'de': {
'dropdowntree': {
'noRecordsTemplate': 'Keine Datensätze gefunden',
'actionFailureTemplate': 'Fehler beim Laden von Daten',
'overflowCountTemplate': 'und ${count} weitere',
'totalCountTemplate': '${count} Elemente ausgewählt'
}
},
'pt': {
'dropdowntree': {
'noRecordsTemplate': 'Nenhum registro encontrado',
'actionFailureTemplate': 'Erro ao carregar dados',
'overflowCountTemplate': 'e mais ${count}',
'totalCountTemplate': '${count} elementos selecionados'
}
},
'ja': {
'dropdowntree': {
'noRecordsTemplate': 'レコードが見つかりません',
'actionFailureTemplate': 'データの読み込みに失敗しました',
'overflowCountTemplate': '他に${count}件',
'totalCountTemplate': '${count}件選択'
}
},
'ar': {
'dropdowntree': {
'noRecordsTemplate': 'لم يتم العثور على سجلات',
'actionFailureTemplate': 'خطأ في تحميل البيانات',
'overflowCountTemplate': 'و ${count} أكثر',
'totalCountTemplate': '${count} عناصر محددة'
}
}
});
function MultiLocaleDropdownTree() {
const [locale, setLocale] = useState('en');
const localeInfo = {
'en': { label: 'English', flag: '🇺🇸' },
'es': { label: 'Español', flag: '🇪🇸' },
'fr': { label: 'Français', flag: '🇫🇷' },
'de': { label: 'Deutsch', flag: '🇩🇪' },
'pt': { label: 'Português', flag: '🇵🇹' },
'ja': { label: '日本語', flag: '🇯🇵' },
'ar': { label: 'العربية', flag: '🇸🇦' }
};
const demoData = [
{ id: 1, name: 'Electronics', parentId: null, expanded: true },
{ id: 2, name: 'Computers', parentId: 1 },
{ id: 3, name: 'Mobile Devices', parentId: 1 },
{ id: 4, name: 'Accessories', parentId: 1 },
];
return (
<div style={{ padding: '20px' }}>
<h2>Multi-Language Dropdown Tree</h2>
<div style={{ marginBottom: '20px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
{Object.entries(localeInfo).map(([code, { label, flag }]) => (
<button
key={code}
onClick={() => setLocale(code)}
style={{
padding: '8px 12px',
backgroundColor: locale === code ? '#007bff' : '#f0f0f0',
color: locale === code ? 'white' : 'black',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontWeight: locale === code ? 'bold' : 'normal'
}}
>
{flag} {label}
</button>
))}
</div>
<DropDownTreeComponent
id="dropdowntree"
fields={{
dataSource: demoData,
value: 'id',
text: 'name',
parentValue: 'parentId'
}}
locale={locale}
showCheckBox={true}
showSelectAll={true}
allowFiltering={true}
placeholder="Select an item"
/>
</div>
);
}
export default MultiLocaleDropdownTree;Runtime Locale Switching
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { L10n, setCulture } from '@syncfusion/ej2-base';
// Pre-define locales
L10n.load({...localeDefinitions...});
function App() {
const [culture, setCultureState] = useState('en');
const handleCultureChange = (newCulture) => {
setCultureState(newCulture);
setCulture(newCulture); // Update global culture
};
return (
<div>
<select onChange={(e) => handleCultureChange(e.target.value)}>
<option value="en">English</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
</select>
<DropDownTreeComponent
locale={culture}
fields={{...}}
/>
</div>
);
}RTL Support
Full Right-to-Left (RTL) language support for Arabic, Hebrew, Urdu, and other RTL languages.
Enable RTL
import { enableRtl } from '@syncfusion/ej2-base';
// Enable RTL globally
enableRtl(true);
<DropDownTreeComponent
fields={{...}}
/>HTML Level RTL
<html dir="rtl" lang="ar">
<body>
<div id="root"></div>
</body>
</html>Component-Level RTL
<DropDownTreeComponent
fields={{...}}
enableRtl={true}
/>RTL Example - Arabic
const arabicData = [
{ id: 1, name: 'الإلكترونيات', parentId: null, expanded: true },
{ id: 2, name: 'أجهزة الكمبيوتر', parentId: 1 },
{ id: 3, name: 'الهواتف الذكية', parentId: 1 },
];
function App() {
return (
<div dir="rtl" lang="ar">
<DropDownTreeComponent
fields={{
dataSource: arabicData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
placeholder="اختر عنصرا"
enableRtl={true}
/>
</div>
);
}Testing RTL
Verify that:
- Text flows right to left
- Dropdown arrow aligns correctly
- Checkboxes appear on right side
- Expand/collapse arrows point correctly
- Keyboard navigation works properly
Complete Accessible Example
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { enableRtl } from '@syncfusion/ej2-base';
import '@syncfusion/ej2-dropdowns/styles/material.css';
function AccessibleDropdownTree() {
const departmentData = [
{ id: 1, name: 'Engineering (25 people)', expanded: true },
{ id: 2, name: 'Frontend Team (10 people)', parentId: 1 },
{ id: 3, name: 'Backend Team (15 people)', parentId: 1 },
{ id: 4, name: 'Sales (12 people)' },
];
return (
<div style={{ padding: '20px' }}>
<form>
<fieldset>
<legend>Select Your Department</legend>
<label htmlFor="deptSelect" id="deptLabel">
Department Selection <span aria-label="required">*</span>
</label>
<DropDownTreeComponent
id="deptSelect"
ref={treeRef}
fields={{
dataSource: departmentData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
placeholder="Select your department"
aria-labelledby="deptLabel"
aria-describedby="deptHelp"
showCheckBox={true}
showSelectAll={true}
treeSettings={{ autoCheck: true }}
/>
<small id="deptHelp">
Use arrow keys to navigate. Press Space to select.
Press Alt+Down to open, Escape to close.
</small>
</fieldset>
</form>
</div>
);
}
export default AccessibleDropdownTree;Advanced Features & API Reference
Table of Contents
- All Component Properties
- Property Examples
- Methods & Public APIs
- Events & Event Arguments
- Performance Optimization
- CSS Customization
All Component Properties
Essential Properties
| Property | Type | Default | Description | Example |
|---|---|---|---|---|
id | string | - | Unique component identifier | id="dropdowntree" |
placeholder | string | "" | Input placeholder text | placeholder="Select item" |
enabled | boolean | true | Enable/disable component | enabled={true} |
width | string \ | number | "100%" | Component width |
Selection Properties
| Property | Type | Default | Description | Example |
|---|---|---|---|---|
showCheckBox | boolean | false | Show checkboxes for multi-select | showCheckBox={true} |
showSelectAll | boolean | false | Show Select All checkbox | showSelectAll={true} |
selectAllText | string | "Select All" | Select All label | selectAllText="Check All" |
unSelectAllText | string | "Unselect All" | Unselect All label | unSelectAllText="Uncheck All" |
allowMultiSelection | boolean | false | Enable Ctrl/Shift multi-select | allowMultiSelection={true} |
Template Properties
| Property | Type | Default | Description |
|---|---|---|---|
itemTemplate | string \ | Function \ | JSX |
valueTemplate | string \ | Function \ | JSX |
headerTemplate | string \ | Function \ | JSX |
footerTemplate | string \ | Function \ | JSX |
noRecordsTemplate | string \ | Function \ | JSX |
actionFailureTemplate | string \ | Function \ | JSX |
Filtering Properties
| Property | Type | Default | Description |
|---|---|---|---|
allowFiltering | boolean | false | Enable search/filter bar |
filterType | "StartsWith" \ | "EndsWith" \ | "Contains" |
filterBarPlaceholder | string | "" | Filter bar placeholder |
ignoreCase | boolean | true | Case-insensitive filtering |
ignoreAccent | boolean | false | Ignore diacritics |
Display Mode Properties
| Property | Type | Default | Description |
|---|---|---|---|
mode | "Default" \ | "Delimiter" \ | "Custom" |
delimiterChar | string | ", " | Delimiter for selected items |
customTemplate | string | "${value.length} item(s) selected" | Custom template for selections |
Localization & RTL Properties
| Property | Type | Default | Description |
|---|---|---|---|
locale | string | "en" | Culture/locale code |
enableRtl | boolean | false | Enable right-to-left layout |
enablePersistence | boolean | false | Persist state in localStorage |
Data Binding Properties
| Property | Type | Default | Description |
|---|---|---|---|
fields | FieldsModel | - | Data source and field mapping |
sortOrder | "Ascending" \ | "Descending" \ | "None" |
Popup & Animation Properties
| Property | Type | Default | Description |
|---|---|---|---|
popupHeight | string \ | number | "300px" |
popupWidth | string \ | number | "100%" |
destroyPopupOnHide | boolean | true | Destroy popup on close |
Styling Properties
| Property | Type | Default | Description |
|---|---|---|---|
cssClass | string | "" | Custom CSS classes |
htmlAttributes | object | {} | HTML attributes |
Advanced Properties
| Property | Type | Default | Description |
|---|---|---|---|
changeOnBlur | boolean | true | Fire change event on blur |
enableHtmlSanitizer | boolean | true | Sanitize HTML in templates |
floatLabelType | "Never" \ | "Always" \ | "Auto" |
---
Property Examples
Essential Properties Examples
Basic Component Setup
<DropDownTreeComponent
id="myDropdownTree"
placeholder="Select an item"
enabled={true}
width="300px"
fields={fields}
/>Selection Properties Examples
Checkboxes with Select All
<DropDownTreeComponent
id="dropdowntree"
showCheckBox={true}
showSelectAll={true}
selectAllText="Select All Items"
unSelectAllText="Unselect All"
fields={fields}
/>Multi-Selection with Ctrl/Shift
<DropDownTreeComponent
id="dropdowntree"
allowMultiSelection={true}
fields={fields}
/>Template Properties Examples
Custom Item Template
const itemTemplate = (props) => {
return (
<div style={{ padding: '5px' }}>
<span style={{ marginRight: '10px' }}>🎯</span>
{props.text}
</div>
);
};
<DropDownTreeComponent
id="dropdowntree"
itemTemplate={itemTemplate}
fields={fields}
/>Custom Value Template
const valueTemplate = (props) => {
const values = props.value || [];
return (
<div style={{ color: '#007bff' }}>
Selected: {values.length} item(s)
</div>
);
};
<DropDownTreeComponent
id="dropdowntree"
valueTemplate={valueTemplate}
fields={fields}
/>Custom Header Template
const headerTemplate = () => (
<div style={{
padding: '10px',
backgroundColor: '#f0f0f0',
borderBottom: '1px solid #ddd'
}}>
<strong>Available Options</strong>
</div>
);
<DropDownTreeComponent
id="dropdowntree"
headerTemplate={headerTemplate}
fields={fields}
/>Custom Footer Template
const footerTemplate = () => (
<div style={{
padding: '10px',
backgroundColor: '#f0f0f0',
borderTop: '1px solid #ddd',
textAlign: 'center'
}}>
<small>Total items: {data.length}</small>
</div>
);
<DropDownTreeComponent
id="dropdowntree"
footerTemplate={footerTemplate}
fields={fields}
/>No Records Template
const noRecordsTemplate = () => (
<div style={{ padding: '20px', textAlign: 'center', color: '#999' }}>
<p>No matching items found</p>
</div>
);
<DropDownTreeComponent
id="dropdowntree"
noRecordsTemplate={noRecordsTemplate}
fields={fields}
/>Action Failure Template (Error State)
const actionFailureTemplate = () => (
<div style={{
padding: '20px',
textAlign: 'center',
color: '#d32f2f',
backgroundColor: '#ffebee'
}}>
<div style={{ fontSize: '14px', fontWeight: 'bold' }}>⚠️ Failed to load items</div>
<div style={{ fontSize: '12px', marginTop: '8px' }}>
Connection error. Please try again later.
</div>
</div>
);
<DropDownTreeComponent
id="dropdowntree"
actionFailureTemplate={actionFailureTemplate}
fields={fields}
/>Action Failure Template with Retry Button
const [isRetrying, setIsRetrying] = React.useState(false);
const actionFailureTemplate = () => (
<div style={{
padding: '16px',
textAlign: 'center',
backgroundColor: '#fff3cd',
borderLeft: '4px solid #ffc107'
}}>
<div style={{ fontSize: '13px', fontWeight: '600', color: '#856404' }}>
Unable to load data
</div>
<div style={{ fontSize: '12px', color: '#856404', marginTop: '4px' }}>
{isRetrying ? 'Retrying...' : 'Server connection failed'}
</div>
<button
onClick={() => {
setIsRetrying(true);
// Trigger data refresh after 2 seconds
setTimeout(() => {
treeRef.current?.refresh();
setIsRetrying(false);
}, 2000);
}}
style={{
marginTop: '10px',
padding: '6px 12px',
backgroundColor: '#ffc107',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '12px',
fontWeight: '600'
}}
disabled={isRetrying}
>
{isRetrying ? 'Retrying...' : 'Retry'}
</button>
</div>
);
<DropDownTreeComponent
ref={treeRef}
id="dropdowntree"
actionFailureTemplate={actionFailureTemplate}
fields={{
dataSource: new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor()
}),
value: 'id',
text: 'name'
}}
/>Filtering Properties Examples
Basic Filtering
<DropDownTreeComponent
id="dropdowntree"
allowFiltering={true}
filterType="Contains"
filterBarPlaceholder="Type to search..."
fields={fields}
/>Case-Insensitive Filtering
<DropDownTreeComponent
id="dropdowntree"
allowFiltering={true}
filterType="StartsWith"
ignoreCase={true}
fields={fields}
/>Ignore Accent Filtering
<DropDownTreeComponent
id="dropdowntree"
allowFiltering={true}
filterType="Contains"
ignoreAccent={true}
ignoreCase={true}
fields={fields}
/>Display Mode Properties Examples
Default Display Mode
<DropDownTreeComponent
id="dropdowntree"
mode="Default"
showCheckBox={true}
fields={fields}
/>Delimiter Display Mode
<DropDownTreeComponent
id="dropdowntree"
mode="Delimiter"
delimiterChar=" | "
showCheckBox={true}
fields={fields}
/>Custom Display Mode
<DropDownTreeComponent
id="dropdowntree"
mode="Custom"
customTemplate="${value.length} items selected out of 50"
showCheckBox={true}
fields={fields}
/>Localization & RTL Properties Examples
Enable RTL (Right-to-Left)
<DropDownTreeComponent
id="dropdowntree"
enableRtl={true}
locale="ar"
fields={fields}
/>Localization with Culture - German
<DropDownTreeComponent
id="dropdowntree"
locale="de" // German
fields={fields}
/>Multi-Language Localization Setup
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { L10n } from '@syncfusion/ej2-base';
import React, { useState } from 'react';
// Define localization for multiple languages
L10n.load({
'es': {
'dropdowntree': {
'noRecordsTemplate': 'No se encontraron registros',
'actionFailureTemplate': 'Error al cargar datos',
'overflowCountTemplate': 'y ${count} más',
'totalCountTemplate': '${count} elementos seleccionados'
}
},
'fr': {
'dropdowntree': {
'noRecordsTemplate': 'Aucun enregistrement trouvé',
'actionFailureTemplate': 'Erreur de chargement des données',
'overflowCountTemplate': 'et ${count} plus',
'totalCountTemplate': '${count} éléments sélectionnés'
}
},
'de': {
'dropdowntree': {
'noRecordsTemplate': 'Keine Datensätze gefunden',
'actionFailureTemplate': 'Fehler beim Laden von Daten',
'overflowCountTemplate': 'und ${count} weitere',
'totalCountTemplate': '${count} Elemente ausgewählt'
}
}
});
function MultiLanguageDropdownTree() {
const [locale, setLocale] = useState('en');
return (
<div style={{ padding: '20px' }}>
<div style={{ marginBottom: '20px' }}>
<label>Select Language: </label>
<select
value={locale}
onChange={(e) => setLocale(e.target.value)}
style={{ padding: '6px' }}
>
<option value="en">English</option>
<option value="es">Español (Spanish)</option>
<option value="fr">Français (French)</option>
<option value="de">Deutsch (German)</option>
</select>
</div>
<DropDownTreeComponent
id="dropdowntree"
locale={locale}
showCheckBox={true}
showSelectAll={true}
allowFiltering={true}
fields={fields}
placeholder={locale === 'en' ? 'Select item' : 'Seleccionar'}
/>
</div>
);
}
export default MultiLanguageDropdownTree;Custom Localization Text
<DropDownTreeComponent
id="dropdowntree"
locale="custom"
noRecordsTemplate="Nenhum resultado encontrado (Portuguese)"
actionFailureTemplate="Falha ao carregar dados"
selectAllText="Selecionar Tudo"
unSelectAllText="Desselecionar Tudo"
fields={fields}
/>Locale with RTL Support (Arabic)
import { enableRtl, L10n } from '@syncfusion/ej2-base';
// Enable RTL globally
enableRtl(true);
// Add Arabic localization
L10n.load({
'ar': {
'dropdowntree': {
'noRecordsTemplate': 'لم يتم العثور على سجلات',
'actionFailureTemplate': 'خطأ في تحميل البيانات',
'overflowCountTemplate': 'و ${count} أكثر',
'totalCountTemplate': '${count} عناصر محددة'
}
}
});
<div dir="rtl" lang="ar">
<DropDownTreeComponent
id="dropdowntree"
locale="ar"
enableRtl={true}
placeholder="اختر عنصراً"
fields={arabicData}
/>
</div>Language Switcher Component
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { L10n } from '@syncfusion/ej2-base';
import React, { useState } from 'react';
// Pre-load multiple locales
L10n.load({
'it': {
'dropdowntree': {
'noRecordsTemplate': 'Nessun record trovato',
'actionFailureTemplate': 'Errore nel caricamento dei dati'
}
},
'pt': {
'dropdowntree': {
'noRecordsTemplate': 'Nenhum registro encontrado',
'actionFailureTemplate': 'Erro ao carregar dados'
}
},
'ja': {
'dropdowntree': {
'noRecordsTemplate': 'レコードが見つかりません',
'actionFailureTemplate': 'データの読み込みに失敗しました'
}
}
});
const LANGUAGE_LABELS = {
'en': { name: 'English', flag: '🇺🇸' },
'es': { name: 'Español', flag: '🇪🇸' },
'fr': { name: 'Français', flag: '🇫🇷' },
'de': { name: 'Deutsch', flag: '🇩🇪' },
'it': { name: 'Italiano', flag: '🇮🇹' },
'pt': { name: 'Português', flag: '🇵🇹' },
'ja': { name: '日本語', flag: '🇯🇵' }
};
function LanguageSwitcher() {
const [currentLocale, setCurrentLocale] = useState('en');
return (
<div style={{ padding: '20px' }}>
<div style={{
display: 'flex',
gap: '10px',
marginBottom: '20px',
flexWrap: 'wrap'
}}>
{Object.entries(LANGUAGE_LABELS).map(([code, { name, flag }]) => (
<button
key={code}
onClick={() => setCurrentLocale(code)}
style={{
padding: '8px 16px',
backgroundColor: currentLocale === code ? '#007bff' : '#f0f0f0',
color: currentLocale === code ? 'white' : 'black',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontWeight: currentLocale === code ? 'bold' : 'normal'
}}
>
{flag} {name}
</button>
))}
</div>
<DropDownTreeComponent
id="dropdowntree"
locale={currentLocale}
showCheckBox={true}
allowFiltering={true}
fields={fields}
/>
</div>
);
}
export default LanguageSwitcher;Persist Selection State
<DropDownTreeComponent
id="dropdowntree"
enablePersistence={true}
fields={fields}
/>Data Binding & Sorting Examples
With Sorting
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
sortOrder="Ascending"
/>Popup & Animation Properties Examples
Custom Popup Dimensions
<DropDownTreeComponent
id="dropdowntree"
popupHeight="500px"
popupWidth="400px"
fields={fields}
/>Destroy Popup on Hide
<DropDownTreeComponent
id="dropdowntree"
destroyPopupOnHide={true}
fields={fields}
/>Styling Properties Examples
Custom CSS Classes
<DropDownTreeComponent
id="dropdowntree"
cssClass="premium-theme dark-mode"
fields={fields}
/>
<style>
{`
.premium-theme {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.dark-mode .e-ddtree {
background-color: #2d2d2d;
color: #fff;
}
`}
</style>HTML Attributes
<DropDownTreeComponent
id="dropdowntree"
htmlAttributes={{
'data-test-id': 'dropdown-tree-1',
'aria-label': 'Select items from tree',
'title': 'Click to expand options'
}}
fields={fields}
/>Advanced Properties Examples
Change on Blur
<DropDownTreeComponent
id="dropdowntree"
changeOnBlur={true}
fields={fields}
/>Enable HTML Sanitizer
<DropDownTreeComponent
id="dropdowntree"
enableHtmlSanitizer={true}
itemTemplate={(props) => (
<div dangerouslySetInnerHTML={{__html: props.text}} />
)}
fields={fields}
/>Floating Label Behavior
// Never show floating label
<DropDownTreeComponent
id="dropdowntree"
floatLabelType="Never"
placeholder="Select item"
fields={fields}
/>
// Always show floating label
<DropDownTreeComponent
id="dropdowntree"
floatLabelType="Always"
placeholder="Item Selection"
fields={fields}
/>
// Auto - show floating label only when selected
<DropDownTreeComponent
id="dropdowntree"
floatLabelType="Auto"
placeholder="Choose from list"
fields={fields}
/>---
Methods & Public APIs
Getting Selected Values
getValue()
Returns array of currently selected values.
const treeRef = React.useRef(null);
const handleGetValue = () => {
const selectedValues = treeRef.current.getValue();
console.log('Selected values:', selectedValues); // string[]
};getSelectedNodes()
Returns array of selected item objects with all properties.
const handleGetSelectedNodes = () => {
const selectedNodes = treeRef.current.getSelectedNodes();
selectedNodes.forEach(node => {
console.log('Node:', node.id, node.name);
});
};getCheckedNodes()
Returns array of checked items (when checkboxes enabled).
const handleGetCheckedNodes = () => {
const checkedNodes = treeRef.current.getCheckedNodes();
checkedNodes.forEach(node => {
console.log('Checked:', node.name);
});
};Setting Selections
setValue(value)
Set selected values programmatically.
treeRef.current.setValue(['id1', 'id3', 'id5']);setCheckedNodes(nodes)
Set checked nodes programmatically (with checkboxes).
treeRef.current.setCheckedNodes(['id2', 'id4']);Clearing Selections
clearSelection()
Clear all selected items.
treeRef.current.clearSelection();Text & Display
getText()
Get display text of selected items.
const text = treeRef.current.getText();
console.log('Selected text:', text);Tree Expansion
expandAll()
Expand all collapsible nodes.
treeRef.current.expandAll();collapseAll()
Collapse all expanded nodes.
treeRef.current.collapseAll();expandNode(nodeId)
Expand specific node by value.
treeRef.current.expandNode('parent_id');collapseNode(nodeId)
Collapse specific node by value.
treeRef.current.collapseNode('parent_id');Enable/Disable
disable()
Disable the component.
treeRef.current.disable();enable()
Enable the component.
treeRef.current.enable();Data Refresh
refresh()
Refresh the component and reload data.
treeRef.current.refresh();Events & Event Arguments
change Event
Fires when selected value changes. Provides old and new values.
const handleChange = (args) => {
console.log('Old values:', args.oldValue); // string[]
console.log('New values:', args.value); // string[]
console.log('Is user interaction:', args.isInteracted); // boolean
console.log('Root element:', args.element); // HTMLElement
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onChange={handleChange}
/>ChangeEventArgs Properties:
e(MouseEvent | KeyboardEvent) - Original eventelement(HTMLElement) - Root component elementisInteracted(boolean) - User-triggered vs programmaticoldValue(string[]) - Previous selected valuesvalue(string[]) - Current selected values
select Event
Fires when an item is selected or deselected.
const handleSelect = (args) => {
console.log('Action:', args.action); // 'select' or 'unselect'
console.log('Is user interaction:', args.isInteracted);
console.log('Item element:', args.item); // HTMLLIElement
console.log('Item data:', args.itemData); // { [key: string]: Object }
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onSelect={handleSelect}
/>SelectEventArgs Properties:
action(string) - 'select' or 'unselect'isInteracted(boolean) - User vs programmaticitem(HTMLLIElement) - Selected DOM elementitemData({[key: string]: Object}) - Item data object
dataBound Event
Fires after data binding is complete.
const handleDataBound = (args) => {
console.log('Data loaded:', args.data); // { [key: string]: Object }[]
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onDataBound={handleDataBound}
/>DataBoundEventArgs Properties:
data({[key: string]: Object}[]) - Bound data array
filtering Event
Fires during filter/search operation. Allows custom filtering logic.
const handleFiltering = (args) => {
console.log('Filter text:', args.text);
console.log('Can prevent default:', args.preventDefaultAction);
// Custom filtering logic
if (args.text.length < 2) {
args.preventDefaultAction = true;
}
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
onFiltering={handleFiltering}
/>FilteringEventArgs Properties:
cancel(boolean) - Cancel filteringevent(Event) - Input event objectfields(FieldsModel) - Current field configpreventDefaultAction(boolean) - Override default filteringtext(string) - Filter text input
beforeOpen Event
Fires before popup opens.
const handleBeforeOpen = (args) => {
console.log('Popup about to open');
// args.cancel = true; // Prevent opening
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onBeforeOpen={handleBeforeOpen}
/>popup Event
Fires when popup visibility changes.
const handlePopup = (args) => {
console.log('Popup action:', args.action); // 'open' or 'close'
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onPopup={handlePopup}
/>focus Event
Fires when component receives focus.
const handleFocus = (args) => {
console.log('Component focused');
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onFocus={handleFocus}
/>keyPress Event
Fires when user presses a key.
const handleKeyPress = (args) => {
console.log('Key pressed:', args.key);
};
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
onKeyPress={handleKeyPress}
/>Performance Optimization
Lazy Loading Strategy
<DropDownTreeComponent
id="dropdowntree"
fields={remoteFields}
treeSettings={{
loadOnDemand: true // Load only parent level initially
}}
placeholder="Loads children on demand"
/>Benefits:
- Initial load time reduced by 50-80%
- Lower bandwidth consumption
- Better for 1000+ items
- Caching of expanded nodes
Virtual Scrolling
Enable high-performance rendering for large lists:
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
popupHeight="400px" // Fixed height for scrolling
allowFiltering={true} // Help users narrow down items
/>Data Filtering Client-Side
Implement custom filtering for pre-loaded data:
const handleFiltering = (args) => {
if (args.text.length >= 2) {
args.preventDefaultAction = false;
}
};Remote Data Optimization
const query = new Query()
.from('Employees')
.select('EmployeeID,FirstName') // Only needed fields
.take(50); // Limit records
const fields = {
dataSource: new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor,
pageSize: 50
}),
query: query,
value: 'EmployeeID',
text: 'FirstName'
};CSS Customization
Custom CSS Classes
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
cssClass="my-custom-tree"
/>CSS Selectors for Styling
/* Root element */
.e-ddtree {
width: 300px;
}
/* Input field */
.e-ddtree .e-input-filter {
border-radius: 4px;
}
/* Popup list */
.e-ddtree .e-tree-popup {
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
/* Tree items */
.e-ddtree .e-list-item {
padding: 10px;
}
/* Selected item */
.e-ddtree .e-list-item.e-active {
background-color: #007bff;
color: white;
}
/* Custom class */
.my-custom-tree .e-list-item {
min-height: 40px;
border-bottom: 1px solid #f0f0f0;
}Complete Styling Example
<div style={{
padding: '20px',
borderRadius: '8px',
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
}}>
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
cssClass="styled-tree"
popupHeight="350px"
width="100%"
placeholder="Select from list"
/>
</div>
<style>
{`
.styled-tree {
border-radius: 4px;
border: 2px solid #007bff;
}
.styled-tree .e-list-item {
padding: 12px;
transition: all 0.2s;
}
.styled-tree .e-list-item:hover {
background-color: #f0f8ff;
}
.styled-tree .e-list-item.e-active {
background-color: #007bff;
color: white;
border-radius: 4px;
}
`}
</style>Best Practices
1. Use refs for method calls: Prefer refs over direct DOM manipulation 2. Handle events for UI updates: Use event handlers for data changes 3. Implement error boundaries: Wrap component for error handling 4. Lazy load large datasets: Always use loadOnDemand for 1000+ items 5. Memoize expensive functions: Use useCallback for event handlers 6. Test keyboard navigation: Ensure accessibility with keyboard 7. Monitor performance: Use React DevTools profiler on large lists
Complete Example with All Features
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
function AdvancedDropdownTree() {
const treeRef = React.useRef(null);
const [selectedValues, setSelectedValues] = React.useState([]);
const remoteData = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor,
crossDomain: true,
});
const query = new Query().from('Employees').select('EmployeeID,FirstName').take(10);
const query1 = new Query().from('Orders').select('OrderID,EmployeeID,ShipName').take(5);
const fields = {
dataSource: remoteData,
query: query,
value: 'EmployeeID',
text: 'FirstName',
hasChildren: 'EmployeeID',
child: {
dataSource: remoteData,
query: query1,
value: 'OrderID',
parentValue: 'EmployeeID',
text: 'ShipName'
}
};
const handleChange = (args) => {
setSelectedValues(args.value);
};
const handleGetValues = () => {
const values = treeRef.current.getValue();
console.log('Current values:', values);
};
return (
<div style={{ padding: '20px' }}>
<DropDownTreeComponent
ref={treeRef}
id="dropdowntree"
fields={fields}
showCheckBox={true}
treeSettings={{ loadOnDemand: true, autoCheck: true }}
allowFiltering={true}
filterType="Contains"
mode="Custom"
customTemplate="${value.length} item(s) selected"
onChange={handleChange}
placeholder="Select employees"
/>
<button onClick={handleGetValues} style={{ marginTop: '10px' }}>
Get Selected Values
</button>
<p>Selected: {selectedValues.join(', ')}</p>
</div>
);
}
export default AdvancedDropdownTree;Checkbox & Multi-Selection
Table of Contents
- Basic Checkbox Support
- Multi-Selection Workflow
- Auto-Check Hierarchy
- Select All Feature
- Getting Selected Values
- Clearing Selection
Basic Checkbox Support
Enable checkboxes for multi-selection by setting showCheckBox property to true.
Enable Checkboxes
<DropDownTreeComponent
id="dropdowntree"
fields={{
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
showCheckBox={true}
placeholder="Select multiple items"
/>What happens when enabled:
- Checkbox appears before each item text
- Multiple items can be selected simultaneously
- Selected items remain checked even when popup closes
- Display shows selected items (or count if many)
Example - Product Selection
const products = [
{ id: '1', name: 'Electronics', expanded: true },
{ id: '2', name: 'Laptops', parentId: '1' },
{ id: '3', name: 'Desktops', parentId: '1' },
{ id: '4', name: 'Phones', parentId: '1' },
{ id: '5', name: 'Appliances' },
{ id: '6', name: 'Refrigerators', parentId: '5' },
];
function App() {
return (
<DropDownTreeComponent
id="productTree"
fields={{
dataSource: products,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
showCheckBox={true}
placeholder="Select products"
/>
);
}Multi-Selection Workflow
User Interactions
1. Click dropdown → Opens tree with checkboxes 2. Check items → Click checkbox or item to select 3. Expand/collapse → Click arrow to show/hide children 4. Multiple selections → Check multiple items at different levels 5. Close popup → Selection persists and displays in input
Display Behavior
Single selection: Shows the item text
Selected: "Laptops"Multiple selections: Shows item count or comma-separated list
Selected: "Laptops, Desktops, Phones"
// or
Selected: "+2 more.." (if many items)Access Selected Values
Use the change event (recommended) to track selected values, or keep the component controlled via a value state.
import { useState } from 'react';
function App() {
const [selectedNodes, setSelectedNodes] = useState([]);
const handleChange = (e) => {
// e.value contains the array of selected values in checkbox/multi-select modes
setSelectedNodes(e.value || []);
};
return (
<>
<DropDownTreeComponent
fields={{...}}
showCheckBox={true}
change={handleChange}
/>
<button onClick={() => console.log('Selected:', selectedNodes)}>Get Selected</button>
</>
);
}Auto-Check Hierarchy
Enable hierarchical parent-child checkbox synchronization with autoCheck property.
Without Auto-Check (Default)
<DropDownTreeComponent
showCheckBox={true}
// Parent and child checkboxes are independent
/>Parent and child checkboxes work independently:
- Checking parent does NOT check children
- Checking child does NOT affect parent
- User must manually manage relationships
With Auto-Check
<DropDownTreeComponent
showCheckBox={true}
treeSettings={{
autoCheck: true,
}}
/>Auto-Check Rules:
1. Check parent → All children checked
✓ Electronics
✓ Laptops
✓ Phones
✓ Tablets2. Uncheck parent → All children unchecked
☐ Electronics
☐ Laptops
☐ Phones
☐ Tablets3. Some children checked → Parent shows intermediate state
◐ Electronics (partially checked)
✓ Laptops (checked)
☐ Phones (unchecked)
✓ Tablets (checked)4. All children checked → Parent automatically checked
✓ Electronics
✓ Laptops
✓ Phones
✓ TabletsComplete Example
const categoryData = [
{ id: '1', name: 'Electronics', expanded: true },
{ id: '2', name: 'Laptops', parentId: '1' },
{ id: '3', name: 'HP', parentId: '2' },
{ id: '4', name: 'Dell', parentId: '2' },
{ id: '5', name: 'Phones', parentId: '1' },
{ id: '6', name: 'iPhone', parentId: '5' },
{ id: '7', name: 'Samsung', parentId: '5' },
];
function App() {
const [checked, setChecked] = useState([]);
const handleChange = (e) => {
setChecked(e.value || []);
};
return (
<div style={{ padding: '20px' }}>
<DropDownTreeComponent
id="categoryTree"
fields={{
dataSource: categoryData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
showCheckBox={true}
treeSettings={{ autoCheck: true }}
placeholder="Select categories with auto-check"
change={handleChange}
/>
<button
onClick={() => console.log('Checked nodes:', checked)}
style={{ marginTop: '10px', padding: '8px 16px' }}
>
Get Selected Items
</button>
</div>
);
}
export default App;Select All Feature
Enable "Select All" checkbox in popup header to quickly select/deselect all items.
Enable Select All
<DropDownTreeComponent
showCheckBox={true}
showSelectAll={true}
placeholder="Select items"
/>Behavior:
- Checkbox appears in popup header
- Click to select/deselect ALL items
- Works independently of autoCheck setting
- Useful for large trees with many items
Default Text
By default displays:
- Check header: "Select All"
- Uncheck header: "Unselect All"
Customize Text
<DropDownTreeComponent
showCheckBox={true}
showSelectAll={true}
selectAllText="✓ Select Everything"
unSelectAllText="✗ Deselect Everything"
/>Example - Survey Form
const surveyOptions = [
{ id: '1', name: 'Category A', expanded: true },
{ id: '2', name: 'Option A1', parentId: '1' },
{ id: '3', name: 'Option A2', parentId: '1' },
{ id: '4', name: 'Option A3', parentId: '1' },
{ id: '5', name: 'Category B', expanded: true },
{ id: '6', name: 'Option B1', parentId: '5' },
{ id: '7', name: 'Option B2', parentId: '5' },
];
function App() {
return (
<div>
<h3>Select your preferences</h3>
<DropDownTreeComponent
id="surveyTree"
fields={{
dataSource: surveyOptions,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
showCheckBox={true}
showSelectAll={true}
selectAllText="Check All Preferences"
unSelectAllText="Clear All Preferences"
placeholder="Choose multiple options"
treeSettings={{
autoCheck: true,
}}
/>
</div>
);
}
export default App;Getting Selected Values
Method 1: Use the change event (recommended)
const handleChange = (e) => {
console.log('Checked node IDs:', e.value || []);
};
<DropDownTreeComponent change={handleChange} showCheckBox={true} {...props} />Method 2: Read the change event payload
const handleChange = (e) => {
// e.value contains selected IDs (array) in checkbox/multi-select modes
console.log('Selected values:', e.value || []);
};
<DropDownTreeComponent change={handleChange} showCheckBox={true} {...props} />Method 3: Map selected IDs to full data objects using e.value
const handleChange = (e) => {
const checkedIds = e.value || [];
const selectedItems = data.filter(item => checkedIds.includes(item.id.toString()));
console.log('Full selected data:', selectedItems);
};
<DropDownTreeComponent change={handleChange} showCheckBox={true} {...props} />Clearing Selection
Clear All Selections
// Recommended: call the component `clear()` method via ref, or control `value` via state
const dropdownRef = useRef(null);
const handleClear = () => {
// If you have a ref to the DropDownTree component instance, call clear()
dropdownRef.current && dropdownRef.current.clear();
// Or update the controlled `value` state to an empty array
// setValue([]);
};
<>
<DropDownTreeComponent ref={dropdownRef} {...props} />
<button onClick={handleClear}>Clear All</button>
</>Programmatic Selection
// Use a controlled `value` prop or set component properties instead of modifying internals
const [value, setValue] = useState([]);
const handleSelectSpecific = () => {
setValue(['2', '5', '7']); // Set specific IDs
};
return (
<>
<DropDownTreeComponent value={value} fields={{...}} showCheckBox={true} />
<button onClick={handleSelectSpecific}>Select Laptops & Phones</button>
</>
);Use Cases
Clear selection:
- User clicks reset button
- Form submission complete
- Filter changed
Programmatic selection:
- Pre-select defaults for user
- Restore previous selections
- Implement filter or quick-select buttons
Data Binding
Table of Contents
- Local Data Binding
- Hierarchical Data
- Self-Referential Data
- Remote Data Binding
- DataManager Adaptors
- Load on Demand
- Prevent Node Selection
Local Data Binding
Dropdown Tree supports local JavaScript arrays as data source. The component requires three essential field mappings to render hierarchical data: value (unique identifier), text (display text), and parentValue or child (hierarchy relationship).
Field Mapping
const data = [
{ id: 1, name: 'Parent', children: [...] },
{ id: 2, name: 'Child', parentId: 1 },
];
<DropDownTreeComponent
fields={{
dataSource: data,
value: 'id', // Unique identifier
text: 'name', // Display text
parentValue: 'parentId', // For self-referential
child: 'children' // For hierarchical (nested)
}}
/>Default mappings (if not specified):
- value: 'id'
- text: 'text'
- parentValue: null
Hierarchical Data
Hierarchical data contains nested arrays of objects representing parent-child relationships through nesting.
Example - Product Categories
const hierarchicalData = [
{
code: 'Electronics',
name: 'Electronics',
expanded: true,
children: [
{
code: 'Laptops',
name: 'Laptops',
children: [
{ code: 'HP', name: 'HP Laptop' },
{ code: 'Dell', name: 'Dell Laptop' },
],
},
{
code: 'Phones',
name: 'Mobile Phones',
children: [
{ code: 'iPhone', name: 'Apple iPhone' },
{ code: 'Samsung', name: 'Samsung Galaxy' },
],
},
],
},
{
code: 'Furniture',
name: 'Furniture',
children: [
{ code: 'Chairs', name: 'Chairs' },
{ code: 'Tables', name: 'Tables' },
],
},
];
function App() {
return (
<DropDownTreeComponent
fields={{
dataSource: hierarchicalData,
value: 'code',
text: 'name',
child: 'children',
}}
placeholder="Select a category"
/>
);
}Key points:
- Nesting depth is unlimited
expandedproperty controls initial expansion state- Map the nested array field to
childproperty
Self-Referential Data
Self-referential data uses parent-child references within a flat array structure.
Example - Organizational Structure
const selfReferentialData = [
{ id: 1, pid: null, name: 'CEO', hasChild: true },
{ id: 2, pid: 1, name: 'Manager', hasChild: true },
{ id: 3, pid: 1, name: 'Developer', hasChild: false },
{ id: 4, pid: 2, name: 'Team Lead', hasChild: false },
{ id: 5, pid: 2, name: 'Engineer', hasChild: false },
];
function App() {
return (
<DropDownTreeComponent
fields={{
dataSource: selfReferentialData,
value: 'id',
text: 'name',
parentValue: 'pid',
hasChildren: 'hasChild', // Optional: indicates if item has children
}}
placeholder="Select employee"
/>
);
}Key points:
- Root items have
pid: nullor undefined - Each item references parent by
pid hasChildrenhelps optimize rendering (optional)- Flat structure easier to manage than nested
Field Properties
| Property | Type | Purpose |
|---|---|---|
value | String | Unique identifier |
text | String | Display text in dropdown |
parentValue | String | Parent reference (self-referential) |
child | String | Children array (hierarchical) |
hasChildren | String | Boolean flag for parent nodes |
selectable | String | Boolean - disable selection for specific nodes |
expanded | String | Boolean - initial expand state |
Remote Data Binding
Bind Dropdown Tree to remote data services using DataManager for dynamic, large-scale datasets.
Basic Remote Binding
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
const dataManager = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor(),
});
function App() {
return (
<DropDownTreeComponent
fields={{
dataSource: dataManager,
value: 'EmployeeID',
text: 'FirstName',
hasChildren: 'EmployeeID', // Or check for children
}}
placeholder="Select employee"
/>
);
}Nested Remote - Two Level Binding
const dataManager = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor(),
crossDomain: true,
});
function App() {
return (
<DropDownTreeComponent
fields={{
dataSource: dataManager,
value: 'EmployeeID',
text: 'FirstName',
child: {
dataSource: new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor(),
crossDomain: true,
}),
value: 'OrderID',
parentValue: 'EmployeeID',
text: 'ShipName',
},
}}
placeholder="Select employee then order"
/>
);
}DataManager Adaptors
Choose the appropriate adaptor based on your data service:
ODataAdaptor (Default)
For OData endpoints:
import { DataManager, ODataAdaptor } from '@syncfusion/ej2-data';
const dataManager = new DataManager({
url: 'url',
adaptor: new ODataAdaptor(),
});ODataV4Adaptor
For OData V4 endpoints (modern OData):
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
const dataManager = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor(),
});WebApiAdaptor
For RESTful Web APIs:
import { DataManager, WebApiAdaptor } from '@syncfusion/ej2-data';
const dataManager = new DataManager({
url: 'url',
adaptor: new WebApiAdaptor(),
});UrlAdaptor
For standard HTTP endpoints:
import { DataManager, UrlAdaptor } from '@syncfusion/ej2-data';
const dataManager = new DataManager({
url: 'url',
adaptor: new UrlAdaptor(),
});Load on Demand
Optimize performance with large datasets by loading child items only when parent is expanded (lazy loading).
Enable Load on Demand
<DropDownTreeComponent
fields={{
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'parentId',
hasChildren: 'hasChild', // Required for lazy loading
}}
treeSettings={{
loadOnDemand: true, // Enable lazy loading
}}
placeholder="Select item (lazy loaded)"
/>With Remote Data
const dataManager = new DataManager({
url: 'url',
adaptor: new WebApiAdaptor(),
});
<DropDownTreeComponent
fields={{
dataSource: dataManager,
value: 'id',
text: 'name',
hasChildren: 'hasChild',
child: {
dataSource: new DataManager({
url: 'url',
adaptor: new WebApiAdaptor(),
}),
value: 'id',
parentValue: 'categoryId',
text: 'name',
},
}}
treeSettings={{
loadOnDemand: true,
}}
/>Benefits:
- Reduces initial load time
- Minimizes bandwidth usage
- Improves user experience with large trees
- Scales to massive datasets
Prevent Node Selection
Disable selection for specific tree nodes using the selectable field mapping.
Example - Parent Nodes Non-Selectable
const data = [
{ id: 1, name: 'Parent 1', parentId: null, selectable: false },
{ id: 2, name: 'Child 1.1', parentId: 1, selectable: true },
{ id: 3, name: 'Child 1.2', parentId: 1, selectable: true },
{ id: 4, name: 'Parent 2', parentId: null, selectable: false },
];
<DropDownTreeComponent
fields={{
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'parentId',
selectable: 'selectable', // Only select items with selectable: true
}}
placeholder="Select child items only"
/>Use cases:
- Prevent category selection, only allow leaf nodes
- Gray out disabled options
- Force users to select specific item types
- Enforce business rules in hierarchical structures
Dynamic Selection Control
const data = [
{ id: 1, name: 'Category', parentId: null, isLeaf: false },
{ id: 2, name: 'Product A', parentId: 1, isLeaf: true },
{ id: 3, name: 'Product B', parentId: 1, isLeaf: true },
];
// Map selectable based on isLeaf flag
fields={{
selectable: 'isLeaf', // Only leaf nodes are selectable
}}Performance tip: Mark parent nodes with selectable: false when you only want leaf node selection.
Field Mapping & Custom Data Structures
Table of Contents
- FieldsModel Overview
- Core Fields
- Node State Fields
- Display Enhancement Fields
- Remote Data Fields
- Complete Field Mapping Examples
FieldsModel Overview
The fields property is a FieldsModel object that maps your data structure to the Dropdown Tree component. It tells the component which properties to use for different purposes.
Basic FieldsModel Structure
const fields = {
// Core mapping
dataSource: data, // Data array or DataManager
value: 'id', // Unique identifier field
text: 'name', // Display text field
// Hierarchy
child: 'children', // Child items field (hierarchical)
// OR
parentValue: 'parentId', // Parent reference field (self-referential)
// Optional enhancements
expanded: 'isExpanded', // Initial expand state
hasChildren: 'hasChild', // Indicates if node has children
selectable: 'canSelect', // Whether node can be selected
selected: 'isSelected', // Pre-selected nodes
iconCss: 'icon', // CSS class for icon
imageUrl: 'image', // Image URL for node
htmlAttributes: 'attrs' // HTML attributes object
};
<DropDownTreeComponent fields={fields} />Core Fields
dataSource
Specifies the data array or DataManager instance to populate the tree.
// Local array
const fields = {
dataSource: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' }
],
value: 'id',
text: 'name'
};
// Remote DataManager
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
const fields = {
dataSource: new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor
}),
value: 'id',
text: 'name'
};value
Field name containing the unique identifier for each node. Used for selection tracking and event data.
const data = [
{ itemId: 1, name: 'Item 1' },
{ itemId: 2, name: 'Item 2' }
];
const fields = {
dataSource: data,
value: 'itemId', // Custom identifier field
text: 'name'
};Important: The value field must be unique across all nodes.
text
Field name containing the display text for each node in the dropdown tree.
const data = [
{ id: 1, label: 'Electronics' },
{ id: 2, label: 'Computers' }
];
const fields = {
dataSource: data,
value: 'id',
text: 'label' // Custom text field
};Hierarchy Fields
child (Hierarchical Data)
Field name containing child items array for nested hierarchies. Use this for data where children are nested within parents.
const hierarchicalData = [
{
id: 1,
name: 'Fruits',
children: [
{ id: 2, name: 'Apple', children: [] },
{ id: 3, name: 'Orange', children: [] }
]
},
{
id: 4,
name: 'Vegetables',
children: [
{ id: 5, name: 'Carrot', children: [] }
]
}
];
const fields = {
dataSource: hierarchicalData,
value: 'id',
text: 'name',
child: 'children' // Nested children array
};parentValue (Self-Referential Data)
Field name containing the parent's identifier. Use this for flat arrays where each child references its parent.
const selfReferentialData = [
{ id: 1, name: 'Fruits', parentId: null },
{ id: 2, name: 'Apple', parentId: 1 },
{ id: 3, name: 'Orange', parentId: 1 },
{ id: 4, name: 'Vegetables', parentId: null },
{ id: 5, name: 'Carrot', parentId: 4 }
];
const fields = {
dataSource: selfReferentialData,
value: 'id',
text: 'name',
parentValue: 'parentId' // Parent reference field
};Root nodes have parentValue as null or undefined.
hasChildren
Field name indicating whether a node has children. Useful for lazy loading or UI optimization.
const data = [
{ id: 1, name: 'Fruits', hasChild: true },
{ id: 2, name: 'Apple', hasChild: false },
{ id: 3, name: 'Vegetables', hasChild: true }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'parentId',
hasChildren: 'hasChild' // Boolean field
};Benefits:
- Shows expand arrow even without fetched children
- Required for lazy loading to work properly
- Prevents unnecessary loading attempts on leaf nodes
Node State Fields
expanded
Field name controlling which nodes are initially expanded in the tree.
const data = [
{ id: 1, name: 'Fruits', expanded: true, children: [...] },
{ id: 2, name: 'Vegetables', expanded: false, children: [...] }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
child: 'children',
expanded: 'expanded' // Boolean field
};Result: "Fruits" branch opens automatically, "Vegetables" stays closed.
selected
Field name pre-selecting nodes when the component initializes.
const data = [
{ id: 1, name: 'Fruits', selected: true },
{ id: 2, name: 'Apple', selected: false },
{ id: 3, name: 'Orange', selected: true }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
selected: 'selected' // Boolean field
};Note: Works with single selection (no checkboxes).
selectable
Field name controlling whether a node can be selected. Set to false to disable selection for specific nodes.
const data = [
{ id: 1, name: 'Category', canSelect: false }, // Can't select category
{ id: 2, name: 'Item 1', canSelect: true },
{ id: 3, name: 'Item 2', canSelect: true }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
selectable: 'canSelect'
};Use Cases:
- Disable selection for category headers
- Prevent selection of disabled items
- Create read-only tree branches
Display Enhancement Fields
iconCss
Field name containing CSS class names for icons displayed before node text.
const data = [
{ id: 1, name: 'Documents', icon: 'e-icons e-folder' },
{ id: 2, name: 'Resume.pdf', icon: 'e-icons e-pdf' },
{ id: 3, name: 'Report.docx', icon: 'e-icons e-docx' }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
iconCss: 'icon'
};Using Syncfusion Icons:
const data = [
{ id: 1, name: 'Add', icon: 'e-icons e-add' },
{ id: 2, name: 'Edit', icon: 'e-icons e-edit' },
{ id: 3, name: 'Delete', icon: 'e-icons e-delete' }
];Using Font Awesome:
const data = [
{ id: 1, name: 'Documents', icon: 'fa fa-folder' },
{ id: 2, name: 'File', icon: 'fa fa-file' }
];imageUrl
Field name containing image URLs displayed before or instead of text.
const data = [
{ id: 1, name: 'User 1', image: '/images/user1.jpg' },
{ id: 2, name: 'User 2', image: '/images/user2.jpg' },
{ id: 3, name: 'User 3', image: '/images/user3.jpg' }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
imageUrl: 'image'
};CSS to style images:
.e-ddtree .e-list-item img {
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 8px;
}htmlAttributes
Field name containing HTML attributes object for custom attributes on tree items.
const data = [
{
id: 1,
name: 'Item 1',
attrs: { title: 'Tooltip text', 'data-category': 'important' }
},
{
id: 2,
name: 'Item 2',
attrs: { title: 'Another item', 'data-category': 'normal' }
}
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
htmlAttributes: 'attrs'
};Result: Items render with custom HTML attributes:
<li title="Tooltip text" data-category="important">Item 1</li>Remote Data Fields
query
Query configuration for remote data fetching. Used with DataManager.
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
const data = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
const query = new Query().from('Employees').select('EmployeeID,FirstName,Title').take(10);
const fields = {
dataSource: data,
query: query, // Query for remote data
value: 'EmployeeID',
text: 'FirstName'
};tableName
Table or resource name for server-side queries.
const fields = {
dataSource: new DataManager({
url: 'url',
adaptor: new UrlAdaptor
}),
tableName: 'Employees', // Server resource name
value: 'EmployeeID',
text: 'FirstName'
};Nested Field Mapping for Hierarchical Data
For hierarchical data with children, specify field mapping for child level as well.
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
const remoteData = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
const query = new Query().from('Employees').select('EmployeeID,FirstName').take(5);
const query1 = new Query().from('Orders').select('OrderID,EmployeeID,ShipName').take(5);
const fields = {
// Parent level
dataSource: remoteData,
query: query,
value: 'EmployeeID',
text: 'FirstName',
hasChildren: 'EmployeeID',
// Child level
child: {
dataSource: remoteData,
query: query1,
value: 'OrderID',
parentValue: 'EmployeeID',
text: 'ShipName'
}
};Complete Field Mapping Examples
Example 1: Simple Hierarchical Data
const data = [
{
id: 1,
name: 'Electronics',
children: [
{ id: 2, name: 'Laptops', children: [] },
{ id: 3, name: 'Phones', children: [] }
]
}
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
child: 'children'
};Example 2: Self-Referential with All Fields
const data = [
{ id: 1, name: 'Fruits', parentId: null, expanded: true, hasChild: true, canSelect: true },
{ id: 2, name: 'Apple', parentId: 1, expanded: false, hasChild: false, canSelect: true }
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'parentId',
expanded: 'expanded',
hasChildren: 'hasChild',
selectable: 'canSelect'
};Example 3: With Display Enhancements (Icons & Images)
const data = [
{
id: 1,
name: 'John Doe',
image: '/images/john.jpg',
parentId: null,
hasChild: true
},
{
id: 2,
name: 'New Task',
icon: 'e-icons e-task',
parentId: 1,
hasChild: false
}
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'parentId',
hasChildren: 'hasChild',
imageUrl: 'image',
iconCss: 'icon'
};Example 4: Remote Data with Query
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
const remoteData = new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor
});
const fields = {
dataSource: remoteData,
query: new Query().from('Categories').select('CategoryID,CategoryName'),
value: 'CategoryID',
text: 'CategoryName',
hasChildren: 'CategoryID'
};Field Mapping Best Practices
1. Always specify `value` field: Must be unique across all nodes 2. Use meaningful field names: Match your data structure 3. Specify `hasChildren` for lazy loading: Required for load-on-demand 4. Use `child` for small datasets: Nested structure 5. Use `parentValue` for large datasets: Flat structure, better performance 6. Test field mappings with sample data: Verify all properties are accessible 7. Consider readonly branches: Use selectable: false for categories
Troubleshooting
Issue: Tree shows no items
- Solution: Verify
dataSource,value, andtextfields are correctly mapped
Issue: Child items not appearing
- Solution: Ensure
childorparentValuefield is correctly specified and data structure matches
Issue: Icons not displaying
- Solution: Verify CSS classes exist, check
iconCssfield mapping
Issue: Lazy loading not working
- Solution: Ensure
hasChildrenfield is present and set totruefor parent nodes
Issue: Pre-selected items not showing as selected
- Solution: Verify
selectedfield is present and set correctly
Getting Started with Dropdown Tree
Table of Contents
Dependencies
The Dropdown Tree component requires the following packages:
|-- @syncfusion/ej2-react-dropdowns
|-- @syncfusion/ej2-base
|-- @syncfusion/ej2-data
|-- @syncfusion/ej2-react-base
|-- @syncfusion/ej2-dropdowns
|-- @syncfusion/ej2-lists
|-- @syncfusion/ej2-inputs
|-- @syncfusion/ej2-navigations
|-- @syncfusion/ej2-popups
|-- @syncfusion/ej2-buttonsThese are automatically installed when you install the main package.
Project Setup
Using Vite (Recommended)
Vite provides a faster development environment and optimized builds.
Create a new React project:
npm create vite@latest my-app -- --template react
cd my-app
npm run devOr with TypeScript:
npm create vite@latest my-app -- --template react-ts
cd my-app
npm run devUsing Create React App
For traditional Create React App setup:
npx create-react-app my-app
cd my-app
npm startInstallation
Install the Dropdown Tree package from npm:
npm install @syncfusion/ej2-react-dropdowns --saveThis single command installs all required dependencies listed above.
Basic Implementation
Step 1: Import Components and Styles
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import '@syncfusion/ej2-dropdowns/styles/material.css'; // or other themesStep 2: Prepare Data
Create your hierarchical data source:
const treeData = [
{ id: '1', name: 'Electronics', expanded: true },
{ id: '2', name: 'Laptops', parentId: '1' },
{ id: '3', name: 'Desktops', parentId: '1' },
{ id: '4', name: 'Appliances' },
{ id: '5', name: 'Refrigerators', parentId: '4' },
];Step 3: Create the Component
function App() {
return (
<DropDownTreeComponent
id="dropdowntree"
fields={{
dataSource: treeData,
value: 'id',
text: 'name',
parentValue: 'parentId',
hasChildren: 'isParent'
}}
placeholder="Select an item"
/>
);
}
export default App;Styling
Available Themes
Import the appropriate theme CSS:
// Material theme (default)
import '@syncfusion/ej2-dropdowns/styles/material.css';
// Bootstrap theme
import '@syncfusion/ej2-dropdowns/styles/bootstrap.css';
// Tailwind theme
import '@syncfusion/ej2-dropdowns/styles/tailwind.css';
// Fluent theme
import '@syncfusion/ej2-dropdowns/styles/fluent.css';Global Styles
Apply theme globally in your main CSS file or app entry:
@import '@syncfusion/ej2-dropdowns/styles/material.css';Custom CSS
Override component styles with custom CSS:
.e-dropdowntree .e-list-item {
padding: 10px 15px;
font-size: 14px;
}
.e-dropdowntree .e-input {
border-radius: 4px;
}Minimal Example
Complete working example with TypeScript:
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import '@syncfusion/ej2-dropdowns/styles/material.css';
import React from 'react';
const App: React.FC = () => {
const hierarchicalData = [
{
id: '1',
name: 'Bookstore',
expanded: true,
},
{
id: '2',
name: 'Books',
parentId: '1',
},
{
id: '3',
name: 'Fiction',
parentId: '2',
},
{
id: '4',
name: 'Science Fiction',
parentId: '3',
},
{
id: '5',
name: 'Fantasy',
parentId: '3',
},
{
id: '6',
name: 'Non-Fiction',
parentId: '2',
},
{
id: '7',
name: 'Biography',
parentId: '6',
},
];
return (
<div style={{ padding: '20px' }}>
<h2>Dropdown Tree - Basic Example</h2>
<DropDownTreeComponent
id="dropdowntree"
fields={{
dataSource: hierarchicalData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
placeholder="Select a category"
popupHeight="250px"
/>
</div>
);
};
export default App;Rendering Output
The component renders as:
- An input field with dropdown icon
- Placeholder text when empty
- Selected value when item is chosen
- Popup tree when clicked
First Interaction
1. Click the dropdown input 2. Tree expands showing all available items 3. Click an item to select it 4. Selected value displays in the input field 5. Click again to change selection
Troubleshooting
Component not rendering?
- Verify
DropDownTreeComponentimport is correct - Ensure CSS file is imported before the component
- Check that dataSource contains valid data
Styles not applying?
- Import CSS after component imports
- Verify theme CSS path is correct
- Check browser console for 404 errors
Data not displaying?
- Ensure field mapping matches your data structure
- Verify
dataSourceprop is set - Check that value/text/parentValue field names exist in data
Multi-Selection & Filtering
Table of Contents
- Multi-Selection with Ctrl/Shift Keys
- Display Modes
- Enabling Filtering
- Filter Types
- Filter Configuration Options
- Custom Filtering
Multi-Selection with Ctrl/Shift Keys
The Dropdown Tree supports multi-selection using keyboard modifiers without requiring checkboxes. This is distinct from checkbox-based selection and allows users to select multiple items by:
- Ctrl+Click to toggle individual selections
- Shift+Click to select a range of items
Enable Multi-Selection
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import * as React from 'react';
function App() {
const data = [
{ id: 1, name: 'Discover Music', hasChild: true, expanded: true },
{ id: 2, pid: 1, name: 'Hot Singles' },
{ id: 3, pid: 1, name: 'Rising Artists' },
{ id: 4, pid: 1, name: 'Live Music' },
];
const fields = {
dataSource: data,
value: 'id',
text: 'name',
parentValue: 'pid',
hasChildren: 'hasChild'
};
return (
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowMultiSelection={true}
placeholder="Select multiple items with Ctrl/Shift"
/>
);
}
export default App;Key Differences from Checkboxes:
- No visible checkboxes
- Selection via Ctrl/Shift keys only
- More subtle UI, suitable for minimal interfaces
- Cannot show all selections in input (limited to mode setting)
Display Modes
The mode property controls how selected items are displayed in the input field. Combined with allowMultiSelection or showCheckBox, it provides different visual representations.
Mode: Default
Shows all selected item values separated by a delimiter character (default: comma and space).
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowMultiSelection={true}
mode="Default"
delimiterChar=", "
placeholder="Select multiple items"
/>Display Example: "Hot Singles, Rising Artists, Live Music"
Mode: Delimiter
Displays selected items with a custom delimiter. Similar to Default but emphasizes custom formatting.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
showCheckBox={true}
mode="Delimiter"
delimiterChar=" | "
placeholder="Select items"
/>Display Example: "Hot Singles | Rising Artists | Live Music"
Mode: Custom
Displays a custom template instead of showing all selected values. Useful for space-constrained UIs or custom display logic.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
showCheckBox={true}
mode="Custom"
customTemplate="${value.length} item(s) selected"
placeholder="Select items"
/>Display Example: "3 item(s) selected"
Custom Template Syntax
The customTemplate property supports variable interpolation:
// Count format
customTemplate="${value.length} item(s) selected"
// Formatted count
customTemplate="Selected: ${value.length}"
// With custom styling function
customTemplate={function(value) {
return value.length > 3
? `${value.length} items selected`
: value.join(', ');
}}Enabling Filtering
The filter feature allows users to search through tree items as they type. Enable it with the allowFiltering property.
Basic Filtering
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
filterBarPlaceholder="Search items..."
placeholder="Select an item"
/>Result:
- Filter bar appears above the tree items
- User types to search
- Items matching the filter remain visible
- Non-matching items are hidden
Filtering with Custom Placeholder
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
filterBarPlaceholder="Type to find..."
placeholder="Select from dropdown"
/>Filter Types
The filterType property determines the matching strategy for search queries.
StartsWith (Default)
Matches items that start with the search text.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
filterType="StartsWith"
placeholder="Search by starting text"
/>Example:
- Search: "Hot" → Matches: "Hot Singles"
- Search: "Singles" → No match
EndsWith
Matches items that end with the search text.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
filterType="EndsWith"
placeholder="Search by ending text"
/>Example:
- Search: "Singles" → Matches: "Hot Singles"
- Search: "Hot" → No match
Contains
Matches items containing the search text anywhere in the item.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
filterType="Contains"
placeholder="Search anywhere in item"
/>Example:
- Search: "ing" → Matches: "Rising Artists", "Live Music", "Hot Singles"
- Search: "Live" → Matches: "Live Music"
Filter Configuration Options
Case-Sensitive Filtering
By default, filtering is case-insensitive. Enable case sensitivity with ignoreCase={false}.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
ignoreCase={false}
filterType="Contains"
placeholder="Case-sensitive search"
/>Example:
- Search: "hot" → No match (requires "Hot")
- Search: "Hot" → Matches: "Hot Singles"
Ignore Diacritics/Accents
By default, diacritics are considered. Set ignoreAccent={true} to ignore them.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
ignoreAccent={true}
filterType="Contains"
placeholder="Accent-insensitive search"
/>Example:
- Search: "cafe" → Matches: "café", "cafe", "Café"
- Search: "é" → Matches: "Café" only
Combined Filter Options
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
filterType="Contains"
ignoreCase={true}
ignoreAccent={true}
filterBarPlaceholder="Search (any case, any accent)..."
placeholder="Select item"
/>Custom Filtering
Handle custom filtering logic using the onFiltering event. This allows you to implement custom filter algorithms or external data sources.
Custom Filtering Event
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import * as React from 'react';
function App() {
const data = [
{ id: 1, name: 'Discover Music', hasChild: true, expanded: true },
{ id: 2, pid: 1, name: 'Hot Singles' },
{ id: 3, pid: 1, name: 'Rising Artists' },
];
const fields = { dataSource: data, value: 'id', text: 'name', parentValue: 'pid', hasChildren: 'hasChild' };
const handleFiltering = (args) => {
console.log('Filter text:', args.text); // User's search input
console.log('Can prevent default filtering:', args.preventDefaultAction);
// Implement custom filtering
if (args.text.length > 3) {
// Only filter if more than 3 characters
args.preventDefaultAction = false;
} else {
// Show all if less than 3 characters
args.preventDefaultAction = true;
}
};
return (
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
allowFiltering={true}
onFiltering={handleFiltering}
placeholder="Type to filter"
/>
);
}
export default App;Prevent Default Filtering
Set preventDefaultAction = true to override the default filter behavior completely.
const handleFiltering = (args) => {
// Prevent default filtering
args.preventDefaultAction = true;
// Implement your own logic
// Update the data source manually
// Reset filtering, etc.
};Filtering Event Properties
The filtering event provides:
text(string) - The filter text entered by userevent(Event) - The input event objectfields(FieldsModel) - Current field configurationpreventDefaultAction(boolean) - Flag to prevent default filteringcancel(boolean) - Cancel the filtering operation
Combining Multi-Selection & Filtering
Using multi-selection with filtering provides a powerful search and select interface.
<DropDownTreeComponent
id="dropdowntree"
fields={fields}
showCheckBox={true}
allowFiltering={true}
filterType="Contains"
mode="Custom"
customTemplate="${value.length} item(s) selected"
treeSettings={{ autoCheck: true }}
filterBarPlaceholder="Search and select..."
placeholder="Select multiple items"
/>User Experience: 1. User types in filter bar to narrow down items 2. Checkboxes visible on filtered results 3. User checks/unchecks items to select 4. Selected items counted in custom template 5. Auto-check synchronizes parent-child relationships
Best Practices
1. Choose appropriate filter type: Use "Contains" for general search, "StartsWith" for predictable prefixes 2. Combine with search bar: Provide clear visual feedback when filter bar is available 3. Handle large datasets: Use filtering with lazy loading for performance 4. Consider user intent: For hierarchical data, preserve hierarchy visibility even when filtering 5. Test localization: Some languages may require specific filter configurations
Troubleshooting
Issue: Filter bar not appearing
- Solution: Ensure
allowFiltering={true}is set
Issue: Filtering not working on remote data
- Solution: Implement custom filtering with
onFilteringevent or handle on server-side
Issue: Partial items visible after filtering
- Solution: Adjust
filterTypeor implement custom logic inonFiltering
Issue: Filter bar placeholder not showing
- Solution: Set
filterBarPlaceholderproperty explicitly
Templates
Table of Contents
- Item Template
- Value Template
- Header Template
- No Records Template
- Action Failure Template
- Footer Template
- Template Expression Syntax
Item Template
Customize the content of each list item in the dropdown using itemTemplate property. This allows complex data display with custom formatting and styling.
Basic Item Template
const employeeData = [
{
id: 1,
name: 'Michael Scott',
position: 'Manager',
parentId: null,
expanded: true,
},
{
id: 2,
name: 'Dwight Schrute',
position: 'Assistant Regional Manager',
parentId: 1,
},
{
id: 3,
name: 'Jim Halpert',
position: 'Sales Representative',
parentId: 1,
},
];
function App() {
return (
<DropDownTreeComponent
fields={{
dataSource: employeeData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
itemTemplate={(props) => (
<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
<span style={{ fontWeight: 'bold' }}>{props.name}</span>
<span style={{ fontSize: '12px', color: '#999' }}>
{props.position}
</span>
</div>
)}
placeholder="Select employee"
/>
);
}
export default App;Styling with CSS Classes
const itemTemplate = (props) => (
<div className="employee-item">
<div className="employee-name">{props.name}</div>
<div className="employee-position">{props.position}</div>
</div>
);
// CSS
const styles = `
.employee-item {
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.employee-name {
font-weight: 600;
color: #333;
}
.employee-position {
font-size: 12px;
color: #666;
}
`;Complex Template with Status Indicator
const projectData = [
{
id: 1,
name: 'Website Redesign',
status: 'In Progress',
progress: 75,
parentId: null,
},
{
id: 2,
name: 'Database Migration',
status: 'Completed',
progress: 100,
parentId: 1,
},
{
id: 3,
name: 'API Development',
status: 'Pending',
progress: 0,
parentId: 1,
},
];
function App() {
const getStatusColor = (status) => {
switch (status) {
case 'Completed':
return '#4CAF50';
case 'In Progress':
return '#FFC107';
case 'Pending':
return '#F44336';
default:
return '#999';
}
};
return (
<DropDownTreeComponent
fields={{
dataSource: projectData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
itemTemplate={(props) => (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0' }}>
<span>{props.name}</span>
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
<div
style={{
width: '50px',
height: '4px',
backgroundColor: '#ddd',
borderRadius: '2px',
overflow: 'hidden',
}}
>
<div
style={{
width: `${props.progress}%`,
height: '100%',
backgroundColor: getStatusColor(props.status),
}}
/>
</div>
<span
style={{
fontSize: '11px',
fontWeight: 'bold',
color: getStatusColor(props.status),
}}
>
{props.status}
</span>
</div>
</div>
)}
placeholder="Select project"
/>
);
}
export default App;Value Template
Customize how selected values display in the input field using valueTemplate property.
Basic Value Template
<DropDownTreeComponent
fields={{...}}
valueTemplate={(props) => (
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<span>👤</span>
<span>{props.name}</span>
<span style={{ fontSize: '12px', color: '#999' }}>
({props.position})
</span>
</div>
)}
/>Count Summary
const valueTemplate = (props) => {
// For multiple selections, show count
if (Array.isArray(props)) {
return (
<div>
Selected: <strong>{props.length}</strong> items
</div>
);
}
// For single selection
return <span>{props.name}</span>;
};
<DropDownTreeComponent
fields={{...}}
valueTemplate={valueTemplate}
showCheckBox={true}
/>Custom Format
const valueTemplate = (props) => {
if (Array.isArray(props)) {
const names = props.map(p => p.name).join(', ');
return <span title={names}>{names.substring(0, 50)}...</span>;
}
return props.name;
};Header Template
Customize the popup header using headerTemplate. This appears statically above list items.
Search Header
const [searchText, setSearchText] = React.useState('');
<DropDownTreeComponent
fields={{...}}
headerTemplate={() => (
<div style={{ padding: '10px' }}>
<input
type="text"
placeholder="Search items..."
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
}}
/>
</div>
)}
/>Instructions Header
<DropDownTreeComponent
fields={{...}}
headerTemplate={() => (
<div style={{ padding: '12px', backgroundColor: '#f5f5f5', borderBottom: '1px solid #ddd' }}>
<div style={{ fontSize: '14px', fontWeight: 'bold' }}>Select Categories</div>
<div style={{ fontSize: '12px', color: '#666', marginTop: '4px' }}>
Expand items to see subcategories
</div>
</div>
)}
showCheckBox={true}
/>Action Buttons Header
<DropDownTreeComponent
fields={{...}}
headerTemplate={() => (
<div style={{ padding: '10px', borderBottom: '1px solid #ddd', display: 'flex', gap: '8px' }}>
<button
onClick={() => treeRef.current && treeRef.current.clear()}
style={{ flex: 1, padding: '6px', fontSize: '12px' }}
>
Clear All
</button>
<button
onClick={() => {
// Implement select all logic by updating controlled `value` or data source
}}
style={{ flex: 1, padding: '6px', fontSize: '12px' }}
>
Select All
</button>
</div>
)}
showCheckBox={true}
/>No Records Template
Display custom content when no items match the filter or when data is empty.
Simple No Records Message
<DropDownTreeComponent
fields={{...}}
allowFiltering={true}
noRecordsTemplate={() => (
<div style={{ padding: '20px', textAlign: 'center', color: '#999' }}>
No matching items found
</div>
)}
/>Enhanced No Records Template
const noRecordsTemplate = () => (
<div style={{
padding: '30px 20px',
textAlign: 'center',
backgroundColor: '#f9f9f9'
}}>
<div style={{ fontSize: '18px', marginBottom: '8px' }}>🔍</div>
<div style={{ fontWeight: 'bold', marginBottom: '4px' }}>No Results</div>
<div style={{ fontSize: '12px', color: '#666' }}>
Try a different search term or adjust filters
</div>
</div>
);
<DropDownTreeComponent
fields={{...}}
allowFiltering={true}
noRecordsTemplate={noRecordsTemplate}
/>Action Failure Template
Display custom error message when data loading fails (remote data errors).
Basic Error Message
const actionFailureTemplate = () => (
<div style={{
padding: '20px',
textAlign: 'center',
color: '#d32f2f'
}}>
❌ Failed to load items
</div>
);
<DropDownTreeComponent
fields={{
dataSource: new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor()
}),
value: 'id',
text: 'name'
}}
actionFailureTemplate={actionFailureTemplate}
/>Error Template with Details
const actionFailureTemplate = () => (
<div style={{
padding: '16px',
backgroundColor: '#ffebee',
borderLeft: '4px solid #d32f2f',
borderRadius: '4px'
}}>
<div style={{
fontWeight: 'bold',
color: '#c62828',
marginBottom: '8px'
}}>
⚠️ Error Loading Data
</div>
<div style={{
fontSize: '12px',
color: '#c62828',
lineHeight: '1.5'
}}>
Unable to connect to the server. Please check your internet connection
and try again.
</div>
</div>
);
<DropDownTreeComponent
fields={{...}}
actionFailureTemplate={actionFailureTemplate}
/>Error Template with Retry
import React, { useRef, useState } from 'react';
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
function DropdownTreeWithRetry() {
const treeRef = useRef(null);
const [isLoading, setIsLoading] = useState(false);
const handleRetry = () => {
setIsLoading(true);
// Simulate retry with delay
setTimeout(() => {
if (treeRef.current) {
treeRef.current.refresh();
}
setIsLoading(false);
}, 2000);
};
const actionFailureTemplate = () => (
<div style={{
padding: '20px',
textAlign: 'center',
backgroundColor: '#fff3cd',
borderRadius: '4px'
}}>
<div style={{
fontSize: '14px',
fontWeight: 'bold',
color: '#856404',
marginBottom: '12px'
}}>
Connection Failed
</div>
<button
onClick={handleRetry}
disabled={isLoading}
style={{
padding: '8px 16px',
backgroundColor: '#ffc107',
color: '#000',
border: 'none',
borderRadius: '4px',
cursor: isLoading ? 'not-allowed' : 'pointer',
fontWeight: 'bold',
opacity: isLoading ? 0.6 : 1
}}
>
{isLoading ? 'Retrying...' : 'Retry Connection'}
</button>
</div>
);
return (
<DropDownTreeComponent
ref={treeRef}
fields={{
dataSource: new DataManager({
url: 'url',
adaptor: new ODataV4Adaptor()
}),
value: 'id',
text: 'name'
}}
actionFailureTemplate={actionFailureTemplate}
/>
);
}
export default DropdownTreeWithRetry;Footer Template
Customize the popup footer using footerTemplate. This appears statically below list items.
Count Summary Footer
<DropDownTreeComponent
fields={{...}}
showCheckBox={true}
footerTemplate={(props) => (
<div style={{ padding: '10px', borderTop: '1px solid #ddd', backgroundColor: '#f9f9f9', fontSize: '12px', color: '#666' }}>
Total items available: <strong>{data.length}</strong>
</div>
)}
/>Selection Count
// Recommended: track selected count via `change` event and component state
const [selectedCount, setSelectedCount] = useState(0);
const handleChange = (e) => {
setSelectedCount((e.value || []).length);
};
const footerTemplate = () => (
<div style={{ padding: '10px', borderTop: '1px solid #ddd', display: 'flex', justifyContent: 'space-between', fontSize: '12px' }}>
<span>Selected: <strong>{selectedCount}</strong></span>
<span>Total: <strong>{data.length}</strong></span>
</div>
);
<DropDownTreeComponent footerTemplate={footerTemplate} change={handleChange} showCheckBox={true} fields={{...}} />Actions Footer
<DropDownTreeComponent
fields={{...}}
footerTemplate={() => (
<div style={{ padding: '10px', borderTop: '1px solid #ddd', display: 'flex', gap: '8px' }}>
<button
onClick={() => console.log('Save selections')}
style={{ flex: 1, padding: '8px', backgroundColor: '#4CAF50', color: 'white', border: 'none', borderRadius: '4px' }}
>
Confirm
</button>
<button
onClick={() => console.log('Cancel')}
style={{ flex: 1, padding: '8px', backgroundColor: '#f44336', color: 'white', border: 'none', borderRadius: '4px' }}
>
Cancel
</button>
</div>
)}
/>Template Expression Syntax
Basic Expression
Use curly braces {...} to access data properties:
// In templates, access properties directly
itemTemplate={(props) => (
<div>{props.id} - {props.name}</div>
)}Conditional Rendering
itemTemplate={(props) => (
<div>
<span>{props.name}</span>
{props.isNew && <span style={{ color: 'red', marginLeft: '8px' }}>NEW</span>}
</div>
)}Array Access
itemTemplate={(props) => (
<div>
{props.tags && props.tags.map((tag, i) => (
<span key={i} style={{ marginRight: '4px' }}>{tag}</span>
))}
</div>
)}Method Calls
const formatPrice = (price) => `$${price.toFixed(2)}`;
itemTemplate={(props) => (
<div>
<span>{props.name}</span>
<span style={{ float: 'right' }}>{formatPrice(props.price)}</span>
</div>
)}Nested Object Access
const data = [
{
id: 1,
name: 'Item',
details: { category: 'A', priority: 'High' }
}
];
itemTemplate={(props) => (
<div>
<span>{props.name}</span>
<span>{props.details?.category}</span>
</div>
)}Template Type Flexibility
Templates accept both function components and HTML strings:
// Function template (recommended)
itemTemplate={(props) => <div>{props.name}</div>}
// Or HTML string (JSX will convert)
itemTemplate="<div>${name}</div>"Complete Template Example
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { useRef } from 'react';
import '@syncfusion/ej2-dropdowns/styles/material.css';
const companyData = [
{
id: 1,
name: 'Engineering',
budget: 500000,
headcount: 25,
expanded: true,
},
{
id: 2,
name: 'Frontend Team',
budget: 200000,
headcount: 10,
parentId: 1,
},
{
id: 3,
name: 'Backend Team',
budget: 300000,
headcount: 15,
parentId: 1,
},
{
id: 4,
name: 'Sales',
budget: 250000,
headcount: 12,
expanded: true,
},
];
function App() {
const treeRef = useRef(null);
return (
<div style={{ padding: '20px' }}>
<h2>Department Selector with Templates</h2>
<DropDownTreeComponent
ref={treeRef}
fields={{
dataSource: companyData,
value: 'id',
text: 'name',
parentValue: 'parentId',
}}
itemTemplate={(props) => (
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0' }}>
<span>{props.name}</span>
<span style={{ fontSize: '12px', color: '#999' }}>
{props.headcount} people | ${props.budget.toLocaleString()}
</span>
</div>
)}
valueTemplate={(props) => (
<div>
<strong>{props.name}</strong>
<span style={{ marginLeft: '8px', color: '#666', fontSize: '12px' }}>
({props.headcount} team members)
</span>
</div>
)}
headerTemplate={() => (
<div style={{ padding: '10px', backgroundColor: '#f0f0f0', fontWeight: 'bold' }}>
Select a Department
</div>
)}
footerTemplate={() => (
<div style={{ padding: '10px', borderTop: '1px solid #ddd', fontSize: '12px', color: '#999' }}>
Total departments: {companyData.length}
</div>
)}
placeholder="Choose department"
/>
</div>
);
}
export default App;Related skills
How it compares
Use syncfusion-react-dropdown-tree for Syncfusion-specific tree dropdowns; use generic React UI skills for headless or non-Syncfusion component libraries.
FAQ
What component does syncfusion-react-dropdown-tree cover?
syncfusion-react-dropdown-tree covers Syncfusion's React Dropdown Tree control for hierarchical selection in forms and dashboards. The skill guides props, data binding, and integration patterns specific to that component.
When should developers use syncfusion-react-dropdown-tree?
syncfusion-react-dropdown-tree fits React builds that already use Syncfusion and need nested selection UIs such as org charts or category trees. Use it during frontend work instead of hand-rolling tree-dropdown behavior.