Showing wrong or invalid DestinationIndex when drag & drop treeview item to gridview's detail area.

beginer
beginer
1544 Points
52 Posts

I'm trying to integrate drag and drop feature form telerik treeview to telerik gridview. But seems , not working as expected, showing wrong or invalid DestinationIndex when drag & drop treeview item to gridview's detail area. I'm using telerik for blazor version 6.0.2. Here is sample code example

<TelerikTreeView Data="@Data"
                 Id="TreeView"
                 @bind-ExpandedItems="@ExpandedItems"
                 Draggable="true"
                 OnDrop="@OnItemDrop"
                 OnDragStart="@OnDragStart"
                 DragThrottleInterval="150"
                 OnDrag="@OnDrag"
                 OnDragEnd="@OnDragEnd">
    <TreeViewBindings>
        <TreeViewBinding ParentIdField="Parent"></TreeViewBinding>
    </TreeViewBindings>
</TelerikTreeView>

<TelerikGrid Data="salesTeamMembers" RowDraggable="true" OnRowDrop="@((GridRowDropEventArgs<MainModel> args) => OnParentRowDropHandler(args))">
    <DetailTemplate>
        @{
            var employee = context as MainModel;
            <TelerikGrid Data="employee.Orders" Pageable="true" PageSize="5" RowDraggable="true" OnRowDrop="@((GridRowDropEventArgs<DetailsModel> args) => OnChildRowDropHandler(args))">
                <GridColumns>
                    <GridColumn Field="OrderId"></GridColumn>
                    <GridColumn Field="DealSize"></GridColumn>
                </GridColumns>
            </TelerikGrid>
        }
    </DetailTemplate>
    <GridColumns>
        <GridColumn Field="Id"></GridColumn>
        <GridColumn Field="Name"></GridColumn>
    </GridColumns>
</TelerikGrid>

@code {
    private string CurrentItem { get; set; }
    private string DestinationItem { get; set; }
    private string Location { get; set; }
    private string Hint { get; set; } = "Documents and its children cannot be moved";
    List<MainModel> salesTeamMembers { get; set; }
private List<TreeItem> Data { get; set; }
    private IEnumerable<object> ExpandedItems { get; set; }

    public class TreeItem
    {
        public int Id { get; set; }
        public int? Parent { get; set; }
        public string Text { get; set; }
        public ISvgIcon Icon { get; set; }
        public bool HasChildren { get; set; }

        public TreeItem(int id, int? parent, string text, ISvgIcon icon, bool hasChildren)
        {
            Id = id;
            Parent = parent;
            Text = text;
            Icon = icon;
            HasChildren = hasChildren;
        }
    }

    private void OnDragStart(TreeViewDragStartEventArgs args)
    {
        var item = args.Item as TreeItem;
        if (item.Parent == 1 || item.Id == 1)
        {
            args.IsCancelled = true;
        }
        else
        {
            CurrentItem = item.Text;
        }
    }

    private void OnDrag(TreeViewDragEventArgs args)
    {
        if (args.DestinationItem != null)
        {
            var destination = args.DestinationItem as TreeItem;
            DestinationItem = destination.Text;
        }
        if (args.DropPosition != null)
        {
            Location = args.DropPosition.Value.ToString().ToLower();
        }
        else
        {
            Location = "over";
        }
    }

    private void OnDragEnd(TreeViewDragEndEventArgs args)
    {
        var destination = args.DestinationItem as TreeItem;
        if (args.DestinationComponentId == "TreeView" && args.DropPosition!=null)
        {
            Hint = "Item was placed successfully";
        }
        else
        {
            Hint = "Invalid location";
        }
        CurrentItem = "";
        Location = "";
        DestinationItem = "";
    }
    private void OnParentRowDropHandler(GridRowDropEventArgs<MainModel> args)
    {
        Console.WriteLine("Parent Grid RowDrop fired");
        Console.WriteLine("Dropped item name: " + args.Item.Name);
        Console.WriteLine("Destination index: " + args.DestinationIndex);
    }

    private void OnChildRowDropHandler(GridRowDropEventArgs<DetailsModel> args)
    {
        Console.WriteLine("Child Grid RowDrop fired");
        Console.WriteLine("Dropped item order id: " + args.Item.OrderId);
        Console.WriteLine("Destination index: " + args.DestinationIndex);
    }
    protected override void OnInitialized()
    {
        salesTeamMembers = GenerateData();
        LoadData();
    }

    private List<MainModel> GenerateData()
    {
        List<MainModel> data = new List<MainModel>();
        for (int i = 0; i < 5; i++)
        {
            MainModel mdl = new MainModel { Id = i, Name = $"Name {i}" };
            mdl.Orders = Enumerable.Range(1, 15).Select(x => new DetailsModel { OrderId = x, DealSize = x ^ i }).ToList();
            data.Add(mdl);
        }
        return data;
    }

    public class MainModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<DetailsModel> Orders { get; set; }
    }

    public class DetailsModel
    {
        public int OrderId { get; set; }
        public double DealSize { get; set; }
    }

    private void OnItemDrop(TreeViewDropEventArgs args)
    {
        Console.WriteLine("Parent Grid RowDrop fired");
        Console.WriteLine("Dropped item name: " + args.DestinationComponentId);
        Console.WriteLine("Destination index: " + args.DestinationIndex);
    }

    private bool IsChild(TreeItem item, TreeItem destinationItem)
    {
        if (destinationItem?.Parent == null || item == null)
        {
            return false;
        }
        else if (destinationItem.Parent?.Equals(item.Id) == true)
        {
            return true;
        }

        var parentDestinationItem = Data.FirstOrDefault(e => e.Id.Equals(destinationItem.Parent));

        return IsChild(item, parentDestinationItem);
    }

    private void LoadData()
    {
        Data = new List<TreeItem>()
        {
            new TreeItem(1, null, "Documents", SvgIcon.Folder, true),
                new TreeItem(2, 1, "report.xlsx", SvgIcon.FileExcel, false),
                new TreeItem(3, 1, "status.docx", SvgIcon.FileWord, false),
                new TreeItem(4, 1, "conferences.xlsx", SvgIcon.FileExcel, false),
                new TreeItem(5, 1, "performance.pdf", SvgIcon.FilePdf, false),
            new TreeItem(6, null, "Pictures", SvgIcon.Folder, true),
                new TreeItem(7, 6, "Camera Roll", SvgIcon.Folder, true),
                    new TreeItem(8, 7, "team.png", SvgIcon.FileImage, false),
                    new TreeItem(9, 7, "team-building.png", SvgIcon.FileImage, false),
                    new TreeItem(10, 7, "friends.png", SvgIcon.FileImage, false),
        };
        ExpandedItems = Data.ToList();
    }

}

Anyone has any idea?

 

Views: 276
Total Answered: 3
Total Marked As Answer: 1
Posted On: 09-Jul-2024 22:54

Share:   fb twitter linkedin
Answers
Priya
Priya
1152 Points
33 Posts
         

Seems some defects are there in the new package UI for Blazor 6.0.2. In earlier packages, there were no drop allowed to detail areas.

Posted On: 15-Jul-2024 22:16
thanks
 - beginer  16-Jul-2024 23:03
Rahul Maurya
Rahul M...
4906 Points
26 Posts
         

There is defect in telerik package 6.0.2. Found a workaround on this. I observed that when row is getting expanded it's creating new table row instead of adding to the expanded row, see in the screenshot:

Here we can see row attribute data-render-row-index has value 2. To fix it, created javascript code to rewrite value to 1:

  1. Create javascipt method in _host.chtml to rewrite index value in expanded rows
    <script>
        window.JsFunction = {
            updateGridDetailRowIndex: function () {
                setTimeout(function () {
                    Array.from(document.getElementsByClassName("k-grid-table")[0].rows).forEach(r => {
                        if (r.getAttribute("class").match("k-expanded")) {
                            prevExpandRow = r;
                        }
                        if (r.getAttribute("class").match("k-detail-row")) {
                            r.setAttribute("data-render-row-index", parseInt(prevExpandRow.getAttribute("data-render-row-index")));
                        }
                    })
                }, 700);
            }
        };
    </script>
  2. Add OnRowExpand event
    <TelerikGrid Data="salesTeamMembers" RowDraggable="true" OnRowDrop="@((GridRowDropEventArgs<MainModel> args) => OnParentRowDropHandler(args))" OnRowExpand="@OnExpand">
  3. Inject IJSRuntime in razor page
    @inject IJSRuntime JSRuntime


  4. Call script method by using IJSRuntime
    async Task OnExpand(GridRowExpandEventArgs args)
    {
        await JSRuntime.InvokeVoidAsync("JsFunction.updateGridDetailRowIndex").ConfigureAwait(false);
    }

Note: It's not a permanet solution but it will resolved the issue.

 

Posted On: 16-Jul-2024 22:47
Thanks.
 - beginer  16-Jul-2024 23:03
Great! Thanks.
 - Harmeet  23-Jul-2024 03:21
Rashmi
Rashmi
1068 Points
19 Posts
         

Thanks all. Here is update, found bug reported on Telerik Feedback Portal. Find details here:

The OnDrop event arguments DestinationIndex and DropPosition are not correctly calculated when a hierarchical Grid row is expanded

 

Posted On: 18-Jul-2024 04:11
 Log In to Chat