Drag and Drop from a Grid to a Treeview

2 Answers 663 Views
Drag and Drop Grid ListBox ListView TreeView
Hvale
Top achievements
Rank 1
Hvale asked on 06 Dec 2021, 06:03 AM

Hello,

I'm new here and I'm trying to figure out how can I drag and drop from a Grid to a TreeView

I found this example http://dojo.telerik.com/eWIgu/2

It's something like this what I want to do, but in the example I can't put an element in a certain node of the TreeView, I just add elements to the data source. So how can I do that? I need your help

 

PS. I also want to do this with a listbox instead of a grid. That's possible?

  
Belish
Top achievements
Rank 1
commented on 11 Jun 2025, 12:21 PM

I am trying to perform like this drag item from kendo Treelist to Drop in Kendo grid but not working in .net code using 
But when I doing drag from treelist to grid I am not event getitng debug 
Razor page code:
<div style="height: 100%;">
    <!-- Parent Grid -->
    <div style="width: 60%; height: 100%; float: left;">
        <h2>{_ParentItem_}s</h2>
        @(Html.Kendo().TreeList<ParentChildModel>()
            .Name("ParentGrid")
            .Columns(columns =>
            {
                columns.Add().Field(p => p.Id).Width(80).Hidden(false);
                columns.Add().Field(p => p.ItemId).Width(80).Hidden(true);
                columns.Add().Field(c => c.Name).Title("Name").Width(140).Template("#= getIndentedName(Name, Id) #");
                columns.Add().Field(e => e.AssetCode).Title("{_AssetCode_}").Width(60);
                columns.Add().Field(e => e.Weight).Title("Weight").Format("{0:n3}").Width(40).Hidden(false);
                columns.Add().Field(e => e.Dimension).Title("Dimension").Width(100).Hidden(false);
                columns.Add().Command(c => 
                { 
                    c.Edit().Text("Edit").ClassName("k-grid-edit");
                    c.Destroy().Text("Delete").ClassName("k-grid-delete");
                }).Title("Actions").Width(80);
            })
            .Editable(editable => editable.Move(move => move.Reorderable(true)).Mode(TreeListEditMode.PopUp)
                .TemplateName("ParentPopupEditor"))
            .Toolbar(toolbar =>
            {
                toolbar.Create().Text("Add New {_ParentItem_}");
                toolbar.Custom().Template(
                    "<div>" +
                    "<input id='toolbarComboBox' style='width: 300px;' />" +
                    "</div>"
                );
                toolbar.Search();
            })
            .DataSource(dataSource => dataSource
                .Read(read => read.Action("GetParentAndChildItems", "ParentChild").Data("parentSearchData"))
                .Create(update => update.Action("AddNewRecord", "ParentChild").Type(HttpVerbs.Post))
                .Update(u => u.Action("UpdateRecord", "ParentChild").Type(HttpVerbs.Post))  //.Data("saveFormData"))
                .Destroy(update => update.Action("DeleteRecord", "ParentChild"))
                .ServerOperation(false)
                .PageSize(20)
                .Model(m =>
                {
                    m.Id(f => f.Id);
                    m.ParentId(f => f.ParentId);
                    m.Expanded(true);
                    m.Field(f => f.ItemId);
                    m.Field(f => f.AssetName);
                    m.Field(f => f.AssetCode);
                    m.Field(f => f.Weight);
                    m.Field(f => f.Dimension);
                })
            )
            .Pageable(x => x.PageSizes(new int[] { 20, 50, 100, 200, 500 }).Refresh(true).Input(true))
            .Sortable()
            .Selectable()
            .Events(e => e.DataBound("dataBound").Save("onEditorDataSave").DragEnd("onDragEnd"))//.DragStart("onDragStart").DragEnd("onDragEnd")
        )
    </div>

    <!-- Assignable Assets -->
    <div style="width: 40%; height: 100%; float: right;">
        <h2>Assignable {_Asset_}s</h2>
        @(Html.Kendo().Grid<ItemDto>()
            .Name("AssetGrid")
            .HtmlAttributes(new { style = "height:100%; width:100%;" })
            .Columns(columns =>
            {
                //columns.Template(@<text> </text>).Draggable(true).Width(30);
                columns.Template("").Draggable(true);
                columns.Bound(a => a.Id).Title("Id").Width(60).HtmlAttributes(new { @class = "idColStyle" });
                columns.Bound(a => a.Title).Title("{_AssetName_}").Width(150);
                columns.Bound(a => a.ItemTypeName).Title("{_AssetType_}").Width(100);
                columns.Bound(a => a.LocationName).Title("Destination {_Location_}").Width(110);
            })
            .ToolBar(toolbar =>
            {
                toolbar.Custom().ClientTemplate(Html.Kendo().Template().AddComponent(c => c
                    .TextBox().Name("toolbarTextBox")
                    .Placeholder("Filter by {_AssetName_}/{_AssetType_}...")
                    .HtmlAttributes(new { style = "float: right; width: 300px;" })
                    .Events(ev => ev.Change("toolbarTextBoxChanged"))
                ));
                toolbar.Search();
            })
            .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(20)
                .ServerOperation(false)
                .Model(m => m.Id("Id")) //Ensure that the Model identifier ("Id") is defined.
                .Read(read => read.Action("GetAssignableAssets", "ParentChild").Data("childrenSearchData"))
            )
            .Pageable()
            .Sortable()
            .Selectable()
            )
    </div>
</div>

JS code:


$(document).ready(function () {
    var treeList = $("#ParentGrid").data("kendoTreeList");
    if (treeList) {
        treeList.dataSource.bind("requestEnd", function (e) {
            if (e.response) {
                if (e.type === "create") {
                    console.log("call requestEnd type: create");
                    treeList.dataSource.read(); // Refresh immediately
                } else if (e.type === "update") {
                    console.log("call requestEnd type: update");
                    setTimeout(function () {
                        treeList.dataSource.read(); // Refresh after 1 second
                    }, 200); // 1000 milliseconds = 1 second
                }
            }
        });
    }
});

function onDragEnd(e) {
    var draggedItem = e.source;         // The dragged item
    var newParent = e.destination;      // The new parent (if changed)
    var newOrder = e.position;  // The new order in the parent

    // Prepare data for backend
    var updateData = {
        sourceId: draggedItem.id,
        destId: newParent ? newParent.id : null,
        destParentId: newParent ? newParent.id : null,
        //sourceItemId = draggedItem.ItemId,
        //destItemId = newParent ? newParent.ItemId : null,
        order: newOrder
    };

    // Make an AJAX call to update the hierarchy/order in the backend
    $.ajax({
        url: "/ParentChild/Reorder", //"/ParentChild/Reorder",
        type: "POST",
        data: {           //{destId: updateData.destId, sourceId: updateData.sourceId, order: updateData.order},
            destId: e.destination.Id,
            sourceId: e.source.Id,
            destParentItemId: e.destination.ParentItemId,
            order: e.position
        },
        //contentType: "application/json",
        success: function () {
            // Optionally refresh the TreeList
            $("#ParentGrid").data("kendoTreeList").dataSource.read();
        },
        error: function () {
            $("#ParentGrid").data("kendoTreeList").dataSource.read();
            alert("Reorder failed (Can't make child asset as parent)");
        }
    });
    console.log("Drag operation ended!", e);
}


// Initialize ParentGrid rows as drop targets
window.initializeDropTargets = function () {
    var draggedItem = null;

    // Make Rows Draggable
    $("#AssetGrid").on("mousedown", "tr", function () {
        var grid = $("#AssetGrid").data("kendoGrid");
        var dataItem = grid.dataItem($(this));
        draggedItem = dataItem; // Track the dragged item's data
        console.log("AssetGrid -> mousedown", draggedItem);
    });

    // Track dragged item from ParentGrid
    $("#ParentGrid").on("mousedown", "tr", function () {
        var parentGrid = $("#ParentGrid").data("kendoTreeList");
        draggedItem = parentGrid.dataItem($(this));
        console.log("ParentGrid -> mousedown", draggedItem);
    });

    $("#ParentGrid").kendoDropTargetArea({
        filter: "tbody tr",
        group: "assetGroup", // Match the draggable group
        drop: function (e) {
            var parentGrid = $("#ParentGrid").data("kendoTreeList"); // Get the Kendo Grid instance
            var dropTargetRow = $(e.dropTarget);    //.closest("#ParentGrid tr.k-table-row.k-master-row"); // The row where the item was dropped
            var targetItem = parentGrid.dataItem(dropTargetRow); // Target row data

            console.log("Dragged Item:", draggedItem.Id);
            console.log("Drop Target:", e.dropTarget);
            console.log("Drop Target Row:", dropTargetRow);
            console.log("Target Item:", targetItem.Id);

            if (targetItem && draggedItem) {
                //alert("Item '" + draggedItem.Title + "' dropped on Parent '" + targetItem.Name + "'");

                // Add AJAX call here to save assignment in the database
                $.ajax({
                    url: "/ParentChild/AssignAsset",
                    method: "POST",
                    data: { parentId: targetItem.Id, itemId: draggedItem.Id, parentItemId: targetItem.ParentItemId },
                    success: function (response) {
                        parentGrid.dataSource.read();
                        $("#AssetGrid").data("kendoGrid").dataSource.read();
                        console.log("AssignAsset ended from kendoDropTargetArea -> drop");
                        //parentGrid.refresh();
                        //alert("Assignment successful!");
                    },
                    error: function () {
                        alert("Error while assigning asset (Can't assign children to child asset).");
                    }
                });
            }
        },
        dragend: function (e) {
            var draggedItem = e.source; // The dragged item
            var newParent = e.destination; // The new parent (if changed)
            var newOrder = e.destinationIndex; // The new order in the parent

            // Prepare data for backend
            var updateData = {
                id: draggedItem.id,
                parentId: newParent ? newParent.id : null,
                order: newOrder
            };

            // Make an AJAX call to update the hierarchy/order in the backend
            $.ajax({
                url: "/ParentChild/Reorder",
                type: "POST",
                data: JSON.stringify(updateData),
                contentType: "application/json",
                success: function () {
                    // Optionally refresh the TreeList
                    $("#TreeList").data("kendoTreeList").dataSource.read();
                    console.log("AssignAsset ended from kendoDropTargetArea -> dragend -> Reorder");
                },
                error: function () {
                    alert("Reorder failed");
                }
            });
        }
    });

    $("#AssetGrid").kendoDropTarget({
        filter: "tbody tr",
        group: "gridGroup", // Match the draggable group
        drop: function (e) {
            var parentGrid = $("#ParentGrid").data("kendoTreeList"); // Get the Kendo Grid instance
            var dropTargetRow = $(e.dropTarget);    //.closest("#ParentGrid tr.k-table-row.k-master-row"); // The row where the item was dropped
            var targetItem = parentGrid.dataItem(dropTargetRow); // Target row data

            console.log("Dragged Item:", draggedItem.Id);
            console.log("Drop Target:", e.dropTarget);
            console.log("Drop Target Row:", dropTargetRow);
            console.log("Target Item:", targetItem.Id);

            if (targetItem && draggedItem) {
                //alert("Item '" + draggedItem.Title + "' dropped on Parent '" + targetItem.Name + "'");

                // Add AJAX call here to save assignment in the database
                $.ajax({
                    url: "/ParentChild/UnAssignAsset",
                    method: "POST",
                    data: { parentId: targetItem.Id, itemId: draggedItem.Id, parentItemId: targetItem.ParentItemId },
                    success: function (response) {
                        parentGrid.dataSource.read();
                        $("#AssetGrid").data("kendoGrid").dataSource.read();
                        console.log("AssignAsset ended from kendoDropTargetArea -> drop");
                        //parentGrid.refresh();
                        //alert("Assignment successful!");
                    },
                    error: function () {
                        alert("Error while assigning asset (Can't assign children to child asset).");
                    }
                });
            }
        }
    });
};



$(document).ready(function () { // Make rows in the AssetGrid draggable $("#AssetGrid").kendoDraggable({ filter: "tbody > tr", // Target rows in the grid hint: function (element) { return $("<div class='k-card k-card-type'><b>" + $(element).find("td:nth-child(2)").text() + "</b></div>"); }, group: "assetGroup" }); var treeList = $("#ParentGrid").data("kendoTreeList"); // Configure drag-and-drop from TreeList to Grid treeList.wrapper.kendoDraggable({ filter: "tr", hint: function (element) { var item = treeList.dataItem(element); console.log("treeList.wrapper.kendoDraggable -> ", item); return element; }, group: "gridGroup" }); window.initializeDropTargets(); });

Neli
Telerik team
commented on 16 Jun 2025, 08:59 AM

Hi Belish,

It is hard to suggest a reason for the observed issue without a runnable sample that demonstrates the issue. However, what I would suggest is

Check Event Bindings - Make sure that the event bindings, such as dragend and drop, are correctly configured and that the functions are being called. You may want to add some console logs or breakpoints to verify that these events are triggered as expected.

- Ensure that the draggable and droppable configurations are correctly initialized. For example, the kendoDraggable and kendoDropTarget should be applied to the correct elements, and the filter should accurately target the elements you intend to drag or drop. Add console logging within the drop and dragend event handlers to ensure they are being triggered. 

Could you please try to initialize the kendoDraggable and DropTarget as demonstrated below and check if the events will be fired correctly and the elements will be dragged:

$(document).ready(function () {
    // Make TreeList rows draggable
    $("#ParentGrid").kendoDraggable({
        filter: "tbody > tr",
        hint: function (element) {
            var item = $("#ParentGrid").data("kendoTreeList").dataItem(element);
            return $("<div class='k-card k-card-type'><b>" + item.Name + "</b></div>");
        },
        group: "sharedGroup"
    });

    // Make Grid rows droppable
    $("#AssetGrid").kendoDropTarget({
        filter: "tbody > tr",
        group: "sharedGroup",
        drop: function (e) {
            var grid = $("#AssetGrid").data("kendoGrid");
            var dropTarget = $(e.dropTarget);
            var targetItem = grid.dataItem(dropTarget);
            console.log("Dropped on:", targetItem);
            // Additional logic to handle the drop event
        }
    });
});

I hope this helps. 

Regards,

Neli

2 Answers, 1 is accepted

Sort by
0
Neli
Telerik team
answered on 09 Dec 2021, 06:55 AM

Hello,

I will need a little bit more time to review the issue. I will get back to you once I have more information to share.

Thank you for your patience

Regards,
Neli
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

0
Neli
Telerik team
answered on 15 Dec 2021, 07:01 AM

Hello Hvale,

Thank you for your patience.

I would suggest you when a node is dropped in the TreeView to find the closest element with the 'k-item' class. Then you could use the TreeView append method to add the node to the TreeView.

$("#treeview").kendoDropTarget({
         drop: function (e) {   
             ......           
             var treeview = $("#treeview").data("kendoTreeView");
             var node = $(e.target).closest(".k-item");             
             treeview.append({subCategoryName: dataItem.ContactName}, node) 
         }
     });

Here is the modified Dojo example. 

Regards,
Neli
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Hvale
Top achievements
Rank 1
commented on 16 Dec 2021, 08:06 PM

Thank you very much for your reply.

I have another question

I realized that I can't drag and drop the items inside the tree view. I think it's because of the .kendoDropTarget, but is there a way to fix it?

Neli
Telerik team
commented on 21 Dec 2021, 09:38 AM

Hi Hvale,

You could execute the logic in the drop event handler only when the draggable instance that leaves the drop target is different than 'treeview'. Below is an example:

 drop: function (e) {             	
         if($(e.draggable.element).attr('id') != 'treeview'){
               ....
        }
}

Here is the modified Dojo example.

Regards,

Neli

Tags
Drag and Drop Grid ListBox ListView TreeView
Asked by
Hvale
Top achievements
Rank 1
Answers by
Neli
Telerik team
Share this question
or