Restrict drag and drop nodes in Angular TreeView component

7 Jan 202510 minutes to read

You are able to restrict drag and drop operations to allow files to be dropped only under folders. This can be achieved by using nodeDragStop and nodeDragging events of TreeView.

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

@Component({
    imports: [
        FormsModule, TreeViewModule
    ],
    standalone: true,
    selector: 'app-container',
    template: `<div id='treeparent'><ejs-treeview id="icons" [fields]='field' sortOder='Ascending' allowDragAndDrop='allowDragAndDrop' (nodeDragStop)='dragStop($event)' (nodeDragging)='nodeDrag($event)'></ejs-treeview></div>`
})
export class AppComponent {
    // Hierarchical data source for TreeView component
    public hierarchicalData: Object[] = [
        {
            nodeId: '01', nodeText: 'Music', icon: 'folder',
            nodeChild: [
                { nodeId: '01-01', nodeText: 'Gouttes.mp3', icon: 'audio' }
            ]
        },
        {
            nodeId: '02', nodeText: 'Videos', icon: 'folder',
            nodeChild: [
                { nodeId: '02-01', nodeText: 'Naturals.mp4', icon: 'video' },
                { nodeId: '02-02', nodeText: 'Wild.mpeg', icon: 'video' },
            ]
        },
        {
            nodeId: '03', nodeText: 'Documents', icon: 'folder',
            nodeChild: [
                { nodeId: '03-01', nodeText: 'Environment Pollution.docx', icon: 'docx' },
                { nodeId: '03-02', nodeText: 'Global Water, Sanitation, & Hygiene.docx', icon: 'docx' },
                { nodeId: '03-03', nodeText: 'Global Warming.ppt', icon: 'ppt' },
                { nodeId: '03-04', nodeText: 'Social Network.pdf', icon: 'pdf' },
                { nodeId: '03-05', nodeText: 'Youth Empowerment.pdf', icon: 'pdf' },
            ]
        },
        {
            nodeId: '04', nodeText: 'Pictures', icon: 'folder', expanded: true,
            nodeChild: [
                {
                    nodeId: '04-01', nodeText: 'Camera Roll', icon: 'folder', expanded: true,
                    nodeChild: [
                        { nodeId: '04-01-01', nodeText: 'WIN_20160726_094117.JPG', image: 'https://ej2.syncfusion.com/demos/src/treeview/images/employees/9.png' },
                        { nodeId: '04-01-02', nodeText: 'WIN_20160726_094118.JPG', image: 'https://ej2.syncfusion.com/demos/src/treeview/images/employees/3.png' },
                    ]
                },
                { nodeId: '04-02', nodeText: 'Wind.jpg', icon: 'images' },
                { nodeId: '04-03', nodeText: 'Stone.jpg', icon: 'images' },
            ]
        },
        {
            nodeId: '05', nodeText: 'Downloads', icon: 'folder',
            nodeChild: [
                { nodeId: '05-01', nodeText: 'UI-Guide.pdf', icon: 'pdf' },
                { nodeId: '05-02', nodeText: 'Tutorials.zip', icon: 'zip' },
                { nodeId: '05-03', nodeText: 'Game.exe', icon: 'exe' },
                { nodeId: '05-04', nodeText: 'TypeScript.7z', icon: 'zip' },
            ]
        }
    ];
    public field: Object = { dataSource: this.hierarchicalData, id: 'nodeId', text: 'nodeText', child: 'nodeChild', iconCss: 'icon', imageUrl: 'image' };
    public allowDragAndDrop: boolean = true;

    public nodeDrag(args: DragAndDropEventArgs): void {
        if (args.droppedNode != null && args.droppedNode.getElementsByClassName('folder') && args.droppedNode.getElementsByClassName('folder').length === 0) {
            args.dropIndicator = 'e-no-drop';
        }
    }

    public dragStop(args: DragAndDropEventArgs): void {
        if (args.droppedNode != null && args.droppedNode.getElementsByClassName('folder') && args.droppedNode.getElementsByClassName('folder').length === 0) {
            args.cancel = true;
        }
    }
}
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-navigations/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-inputs/styles/material.css';

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

.e-treeview .e-list-img {
    width: 25px;
    height: 25px;
}

/* Loading sprite image for TreeView */
.e-treeview .e-list-icon {
    background-repeat: no-repeat;
    background-image: url(https://ej2.syncfusion.com/demos/src/treeview/images/icons/file_icons.png);
    height: 20px;
}

/* Specify the icon positions based upon class name */
.e-treeview .e-list-icon.folder {
    background-position: -10px -552px;
}

.e-treeview .e-list-icon.docx {
    background-position: -10px -20px;
}

.e-treeview .e-list-icon.ppt {
    background-position: -10px -48px;
}

.e-treeview .e-list-icon.pdf {
    background-position: -10px -104px;
}

.e-treeview .e-list-icon.images {
    background-position: -10px -132px;
}

.e-treeview .e-list-icon.zip {
    background-position: -10px -188px;
}

.e-treeview .e-list-icon.audio {
    background-position: -10px -244px;
}

.e-treeview .e-list-icon.video {
    background-position: -10px -272px;
}

.e-treeview .e-list-icon.exe {
    background-position: -10px -412px;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));