Node Editing in Angular Tree View

31 Aug 202616 minutes to read

The TreeView component provides in-place node editing functionality by setting the allowEditing property to true. To directly edit nodes in place, double-click the TreeView node or select the node and press the F2 key.

When editing is completed by losing focus or pressing the Enter key, the modified node’s text is saved automatically. To cancel editing without saving changes, press the Escape key. This discards the edited text and retains the original TreeView node text.

Programmatic editing

Node editing can also be performed programmatically. Pass a node ID to the beginEdit method to create an inline edit textbox for that node.

@ViewChild('tree') tree: TreeViewComponent;

public editNode(nodeId: string): void {
  this.tree.beginEdit(nodeId); // Opens an inline edit textbox for the specified node
}

You can also wire beginEdit to a button click handler so the user can trigger edit mode from the page instead of a double-click or F2.

Editing events

The component exposes events to validate editing, react to changes, and prevent saves:

Event When it fires Useful event arguments
nodeEditing Before a node enters edit mode (typically on F2 or double-click). Use this event to decide whether editing is allowed. args.node, args.nodeData
nodeEdited Before the edited text is saved (Enter or focus loss). Cancel the save by setting args.cancel = true. Use this event for validation such as disallowing empty text. args.oldText, args.newText, args.node, args.nodeData, args.cancel

The following example shows how to cancel editing in the nodeEdited event when the user enters only whitespace:

public onNodeEdited(args: NodeEditEventArgs): void {
  if (!args.newText || args.newText.trim() === '') {
    args.cancel = true; // Prevent the empty or whitespace text from being saved
  }
}

If the user presses Escape, the editor closes without firing the nodeEdited event.

In the following example, the first level node’s text cannot be changed, but all other level nodes’ text can be modified.

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { TreeViewModule, TreeViewComponent } from '@syncfusion/ej2-angular-navigations'
import { Component, ViewChild } from '@angular/core';
import { NodeCheckEventArgs } from '@syncfusion/ej2-navigations';

@Component({
    imports: [
        FormsModule, TreeViewModule
    ],
    standalone: true,
    selector: 'app-container',
    // specifies the template string for the TreeView component
    template: `<div id='treeparent'><ejs-treeview id='treeelement' [fields]='field' [allowEditing]='allowEditing' (nodeEditing)='editing($event)'></ejs-treeview></div>`
})
export class AppComponent {
    @ViewChild('samples')
    public tree?: TreeViewComponent;
    constructor() {
    }
    // defined the array of data
    public hierarchicalData: Object[] = [
        {
            id: '01', name: 'Local Disk(C:)', expanded: true,
            subChild: [
                {
                    id: '01-01', name: 'Program Files',
                    subChild: [
                        { id: '01-01-01', name: '7-Zip' },
                        { id: '01-01-02', name: 'Git' },
                        { id: '01-01-03', name: 'IIS Express' },
                    ]
                },
                {
                    id: '01-02', name: 'Users', expanded: true,
                    subChild: [
                        { id: '01-02-01', name: 'Smith' },
                        { id: '01-02-02', name: 'Public' },
                        { id: '01-02-03', name: 'Admin' },
                    ]
                },
                {
                    id: '01-03', name: 'Windows',
                    subChild: [
                        { id: '01-03-01', name: 'Boot' },
                        { id: '01-03-02', name: 'FileManager' },
                        { id: '01-03-03', name: 'System32' },
                    ]
                },
            ]
        },
        {
            id: '02', name: 'Local Disk(D:)',
            subChild: [
                {
                    id: '02-01', name: 'Personals',
                    subChild: [
                        { id: '02-01-01', name: 'My photo.png' },
                        { id: '02-01-02', name: 'Rental document.docx' },
                        { id: '02-01-03', name: 'Pay slip.pdf' },
                    ]
                },
                {
                    id: '02-02', name: 'Projects',
                    subChild: [
                        { id: '02-02-01', name: 'ASP Application' },
                        { id: '02-02-02', name: 'TypeScript Application' },
                        { id: '02-02-03', name: 'React Application' },
                    ]
                },
                {
                    id: '02-03', name: 'Office',
                    subChild: [
                        { id: '02-03-01', name: 'Work details.docx' },
                        { id: '02-03-02', name: 'Weekly report.docx' },
                        { id: '02-03-03', name: 'Wish list.csv' },
                    ]
                },
            ]
        },
        {
            id: '03', name: 'Local Disk(E:)', icon: 'folder',
            subChild: [
                {
                    id: '03-01', name: 'Pictures',
                    subChild: [
                        { id: '03-01-01', name: 'Wind.jpg' },
                        { id: '03-01-02', name: 'Stone.jpg' },
                        { id: '03-01-03', name: 'Home.jpg' },
                    ]
                },
                {
                    id: '03-02', name: 'Documents',
                    subChild: [
                        { id: '03-02-01', name: 'Environment Pollution.docx' },
                        { id: '03-02-02', name: 'Global Warming.ppt' },
                        { id: '03-02-03', name: 'Social Network.pdf' },
                    ]
                },
                {
                    id: '03-03', name: 'Study Materials',
                    subChild: [
                        { id: '03-03-01', name: 'UI-Guide.pdf' },
                        { id: '03-03-02', name: 'Tutorials.zip' },
                        { id: '03-03-03', name: 'TypeScript.7z' },
                    ]
                },
            ]
        }
    ];
    // maps the appropriate column to fields property
    public field: Object = { dataSource: this.hierarchicalData, id: 'id', text: 'name', child: 'subChild' };
    // enable the editing options to the TreeView
    public allowEditing: boolean = true;
    //Bind the nodeChecked event
    public editing(args: NodeCheckEventArgs) {
        //check whether node is root node or not
        if (args.node.parentNode?.parentNode?.nodeName !== "LI") {
            args.cancel = true;
        }
    };
}
@import 'node_modules/@syncfusion/ej2-base/styles/material3.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material3.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material3.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material3.css';
@import 'node_modules/@syncfusion/ej2-angular-navigations/styles/material3.css';
@import 'node_modules/@syncfusion/ej2-angular-inputs/styles/material3.css';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

See Also