Drag & drop with remote data not working

Hi,

I have a simple treegrid in a WASM like below:
    <SfTreeGrid Id="TreeGrid" @ref="Treegrid" TValue="TreeNode" Query="@QueryData" AllowRowDragAndDrop="true" AllowSorting="false" TreeColumnIndex="1" IdMapping="Id" ParentIdMapping="ParentId" Toolbar="@(new List<string>() { "Add","Edit", "Update", "Cancel"})" HasChildMapping="IsParent" >
        <SfDataManager Url="/api/NodeEntity" Adaptor="Adaptors.UrlAdaptor"></SfDataManager>
        <TreeGridColumns>
            <TreeGridColumn Field="Id" HeaderText="Id" IsPrimaryKey="true" Width="10" Visible="false"></TreeGridColumn>
            <TreeGridColumn Field="SortOrder" HeaderText="Order" Width="100" Visible="false"></TreeGridColumn>
            <TreeGridColumn Field="Name" HeaderText="Name" Width="100"></TreeGridColumn>
        </TreeGridColumns>
    </SfTreeGrid>

My data is displaying correctly, but if I try to drag/drop within the treegrid, I get an error like below:

blazor.webassembly.js:1 Uncaught (in promise) Error: System.ArgumentNullException: Value cannot be null. (Parameter 'source')
   at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
   at System.Linq.Enumerable.Count[ExpandoObject](IEnumerable`1 source)
   at Syncfusion.Blazor.TreeGrid.Internal.RowDD`1.<ReorderRows>d__17[[RapportExpert2021.Shared.Models.TreeNode, RapportExpert2021.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at Syncfusion.Blazor.TreeGrid.Internal.GridRenderer`1.<ReorderRows>d__81[[RapportExpert2021.Shared.Models.TreeNode, RapportExpert2021.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
    at Object.endInvokeDotNetFromJS (blazor.webassembly.js:1)
    at Object.invokeJSFromDotNet (blazor.webassembly.js:1)
    at Object.w [as invokeJSFromDotNet] (blazor.webassembly.js:1)
    at _mono_wasm_invoke_js_blazor (dotnet.5.0.1.js:1)
    at do_icall (<anonymous>:wasm-function[10596]:0x194e58)
    at do_icall_wrapper (<anonymous>:wasm-function[3305]:0x79df9)
    at interp_exec_method (<anonymous>:wasm-function[2155]:0x44ad3)
    at interp_runtime_invoke (<anonymous>:wasm-function[7862]:0x12efff)
    at mono_jit_runtime_invoke (<anonymous>:wasm-function[7347]:0x118e5f)
    at do_runtime_invoke (<anonymous>:wasm-function[3304]:0x79d42)

This works fine if the data is local.  But when I use a controller (generated via scaffoling), then it stop working.

Thanks,

ma

8 Replies 1 reply marked as answer

PS Pon Selva Jeganathan Syncfusion Team December 28, 2020 12:24 PM UTC

Hi Martin   
    
Thanks for contacting syncfusion forum.    
    
We are able to replicate the problem at our end in your specified scenario(Drag & drop with remote data not working) with that latest version. Further analyzing we have confirmed this issue Script Error thrown when drag and drop row with remote data” as bug. Thank you for the taking the time to report the issue and helping us improve our product. At Syncfusion we are committed to fixing all the validated defect (subject to technological feasibility and Product Development Life Cycle) and including its fix in our subsequent release. The fix for the issue will be included in Second week of January 2021 patch release.    
    
You can track the current status of your request, review the resolution timeline and contact us for any further inquiries through this link.        
  
Note: To view the above feedback, kindly login into your account.        
    
Please get back to us if you need any further assistance.    
    
Regards,   
Pon selva    
  




MA Martin Ares February 13, 2021 09:22 PM UTC

Hi, any update on this?

Thanks,

ma


PK Padmavathy Kamalanathan Syncfusion Team February 16, 2021 02:10 PM UTC

Hi Martin, 
 
Sorry for the inconvenience caused. Due to some dependent issues, we could not include the fix for this issue (“Script Error thrown when drag and drop row with remote data”) as promised. Fix for this issue will be included in our upcoming nuget release which is expected to be rolled out on 23rd February 2021.  
 
 
Until then we appreciate your patience. 
 
Regards, 
Padmavathy Kamalanathan           
 



MA Martin Ares March 23, 2021 09:43 PM UTC

Hi, would you have any update on this?

Thanks,

ma


PK Padmavathy Kamalanathan Syncfusion Team March 24, 2021 12:31 PM UTC

Hi Martin, 
 
We appreciate your patience. 
 
Query: Script Error thrown when drag and drop row with remote data 
 
We are glad to announce that fix for the issue "Script Error thrown when drag and drop row with remote data" has been rolled out in our nuget release. We request you to update to our latest version "18.4.0.49". 
 
We need to handle Row Drag and Drop with remote data at server end(i.e based on row drag and drop of record, we need to remove and add record at the dropped position in RowDropped event). Please check the below sample for Row Drag and Drop handling with remote data, 
 
Using the above solution, we can drag and drop records. But it will not be dropped at right position since we have not provided support for accessing “dropPosition” from the arguments of RowDropped event yet. We have already considered it as feature improvement and logged report for the same. Support for this dropPosition in RowDropped event will be included in our nuget release which is expected to be rolled out in 1st week of April 2021. 
 
You can track the current status of your request, review the proposed resolution timeline and contact us for any further queries through this link, 
 
 
Note: To view the above feedback, kindly login into your account. 
 
Once the dropPosition is included, based on the dropPosition ( topSegment- above a record/bottomSegment- below a record/middgleSegment- as child a record) we can perform row drag and drop and insert record above/below a record or as children to a record. 
 
Kindly get back to us for further assistance. 
 
Regards, 
Padmavathy Kamalanathan 



PK Padmavathy Kamalanathan Syncfusion Team April 15, 2021 12:24 PM UTC

Hi Martin, 
 
We appreciate your patience. 
 
We are glad to announce that “Support for the dropPosition in RowDropped event” has been rolled out in our nuget release. We request you to update to our latest version "19.1.56". 
 
Also as we have mentioned earlier, we need to handle Row Drag and Drop with remote data at server end(i.e based on dragged record and drop position, we need to remove and add record at the dropped position in RowDropped event). 
 
In Tree Grid Row Drag and Drop, we have 3 drop positions. 
  1. Above a record(top position)
  2. Below a record(bottom position)
  3. As a child to a record(middle position)
 
We can access below details from the arguments of RowDropped event, using which we need to handle RowDD at sever end 
  1. index of dragged record from args.FromIndex
  2. data of dragged record from args.Data
  3. drop index from args.DropIndex
  4. And position from args.Target.ID
 
Using the above details and position, we need to remove dragged record from it’s actual position and insert it again in new drop position. 
 
We have created sample in which we have handled RowDD at server end. Please check the below code snippet and sample, 
 
 
<SfTreeGrid @ref="TreeGrid" TValue="TreeData.BusinessObject" 
            IdMapping="TaskId" ParentIdMapping="ParentId" TreeColumnIndex="1"  
            AllowPaging="true" HasChildMapping="isParent" AllowRowDragAndDrop="true"> 
    <SfDataManager Url="/api/Values" Adaptor="Adaptors.UrlAdaptor"></SfDataManager> 
    <TreeGridEvents TValue="TreeData.BusinessObject"   RowDropped="RowDrop"></TreeGridEvents> 
    <TreeGridSelectionSettings Type="Syncfusion.Blazor.Grids.SelectionType.Multiple"></TreeGridSelectionSettings> 
    <TreeGridColumns> 
        <TreeGridColumn Field="TaskId" HeaderText="Task ID" IsPrimaryKey="true" Width="80"  
            TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right"></TreeGridColumn> 
            ------- 
    </TreeGridColumns> 
</SfTreeGrid> 
@code{ 
    SfTreeGrid<TreeData.BusinessObject> TreeGrid; 
 
    void RowDrop(Syncfusion.Blazor.Grids.RowDragEventArgs<TreeData.BusinessObject> args) 
    { 
        var position = args.Target.ID; // drop position 
        var dropIndex = Convert.ToInt32(args.DropIndex); // drop index 
        var targetData = this.TreeGrid.GetCurrentViewRecords()[dropIndex]; // drop index data 
        var targetDataID = targetData.TaskId; // drop index data's TaskId 
        var index = Convert.ToInt32(args.DropIndex);  // drop index 
        //args.Cancel = true; 
        if (position == " e-droptop" || position == " e-dropbottom") // if a record is dropped below/above another record 
        { 
 
            if (args.Data[0].ParentId != null) // if dragged record has parent 
            { 
                var childCount = 0; 
                int parent1 = (int)args.Data[0].ParentId; 
                childCount += FindChildRecords(parent1); // finding the number of child for dragged record's parent 
                --------- 
            } 
            var data = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault(); 
            //removing dragged record from list 
            TreeData.GetSelfDataSource().Remove(TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault()); 
            data.ParentId = targetData.ParentId; //setting the dropIndex data's parent as parent of dragged record  
 
            if (position == " e-dropbottom") // if a record is dropped below another record 
            { 
                index = index + 1; 
                TreeData.BusinessObjectCollection.Insert(index, data); 
 
            } 
            else if (position == " e-droptop") // if a record is dropped above another record 
            { 
                index = index + FindChildRecords(targetDataID); // find the target record's children count to find drop index 
                TreeData.BusinessObjectCollection.Insert(index, data); 
 
            } 
        } 
 
        else if (position == " e-dropchild") // if a record is dropped as child to another record(middle segment) 
        { 
            var data = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault(); 
            var dropData = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == targetDataID).FirstOrDefault(); 
            // removing dragged record from list 
            TreeData.GetSelfDataSource().Remove(TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault()); 
            dropData.isParent = true; //set isParent property(hasChildMapping) of target record to false 
            data.ParentId = targetDataID; //setting the dropIndex data's ID as parent of dragged record 
            index = index + 1; 
            TreeData.BusinessObjectCollection.Insert(index, data); 
 
        } 
    } 
} 
 
 
 
Kindly get back to us for further assistance. 
 
Regards, 
Padmavathy Kamalanathan 


Marked as answer

GG Gernot Gutschi February 18, 2023 09:35 AM UTC

Hi,

is there a simpler solution using a CustomAdapter yet? Why is the Update method of the CustomAdapter not automatically called? Do I really need to check the drop positionmyself?

Best,

Gernot



PS Pon Selva Jeganathan Syncfusion Team February 22, 2023 05:06 PM UTC

Hi Gernot Gutschi,


Query: is there a simpler solution using a CustomAdapter yet? Why is the Update method of the CustomAdapter not automatically called? Do I really need to check the drop positionmyself?


Regarding your query, when using Row Drag and Drop with a custom adapter, you will need to handle the drag and drop operation. Based on the dragged record and the drop position, you will need to remove and add the record at the dropped position.


As for the Update method of the CustomAdapter, it is not automatically called during the drag and drop operation. So you will need to manually handle the drop position.


Please refer to the below code snippet,


<SfTreeGrid @ref="treeGrid" TValue="TreeData.BusinessObject"

            HasChildMapping="isParent" IdMapping="TaskId" ParentIdMapping="ParentId" AllowRowDragAndDrop="true"

            TreeColumnIndex="1" >

    <SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager>

      <TreeGridEvents TValue="TreeData.BusinessObject" RowDropped="Dropping" ></TreeGridEvents>

        <TreeGridColumns>

        <TreeGridColumn Field="TaskId" HeaderText="Task ID" IsPrimaryKey="true" Width="80" ….

</SfTreeGrid>

@code{

….

 

    protected override void OnInitialized()

    {

        TreeGridData = TreeData.GetSelfDataSource().ToList();

    }

 

    private void Dropping(Syncfusion.Blazor.Grids.RowDragEventArgs<TreeData.BusinessObject> args)

    {

        var position = args.Target.ID; // drop position

        var dropIndex = Convert.ToInt32(args.DropIndex); // drop index

        var targetDataID = treeGrid.GetCurrentViewRecords()[dropIndex].TaskId; // drop index data's TaskId

        var targetData = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == targetDataID).FirstOrDefault();

        var index = Convert.ToInt32(args.DropIndex);  // drop index

        if (position == " e-droptop" || position == " e-dropbottom") // if a record is dropped below/above another record

        {

            if (args.Data[0].ParentId != null) // if dragged record has parent

            {

                var childCount = 0;

                int parent1 = (int)args.Data[0].ParentId;

                childCount += FindChildRecords(parent1); // finding the number of child for dragged record's parent

                if (childCount == 1) // if the dragged record is the only child for a particular record

                {

                    var i = 0;

                    for (; i < TreeData.GetSelfDataSource().Count; i++)

                    {

                        if (TreeData.GetSelfDataSource()[i].TaskId == parent1)

                        {

                            //set isParent of dragged record's parent to false

                            TreeData.GetSelfDataSource()[i].isParent = null;

                            break;

                        }

                        if (TreeData.GetSelfDataSource()[i].TaskId == args.Data[0].TaskId)

                        {

                            //set parentItem of dragged record to null

                            TreeData.GetSelfDataSource()[i].ParentId = null;

                            break;

                        }

 

 

                    }

                }

            }

            var data = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault();

            //removing dragged record from list

            TreeData.GetSelfDataSource().Remove(TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault());

            data.ParentId = targetData.ParentId; //setting the dropIndex data's parent as parent of dragged record

 

            if (position == " e-dropbottom") // if a record is dropped below another record

            {

                index = TreeData.BusinessObjectCollection.IndexOf(targetData);

                index = index + 1;

                TreeData.BusinessObjectCollection.Insert(index, data);

 

            }

            else if (position == " e-droptop") // if a record is dropped above another record

            {

                index = TreeData.BusinessObjectCollection.IndexOf(targetData);

                index = index + FindChildRecords(targetDataID); // find the target record's children count to find drop index

                TreeData.BusinessObjectCollection.Insert(index, data);

 

            }

        }

 

        else if (position == " e-dropchild") // if a record is dropped as child to another record(middle segment)

        {

            var data = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault();

            var dropData = TreeData.GetSelfDataSource().Where(ds => ds.TaskId == targetDataID).FirstOrDefault();

            // removing dragged record from list

            TreeData.GetSelfDataSource().Remove(TreeData.GetSelfDataSource().Where(ds => ds.TaskId == args.Data[0].TaskId).FirstOrDefault());

            dropData.isParent = true; //set isParent property(hasChildMapping) of target record to false

            data.ParentId = targetDataID; //setting the dropIndex data's ID as parent of dragged record

            index = index + 1;

            TreeData.BusinessObjectCollection.Insert(index, data);

 

        }

        TreeGridData = TreeData.BusinessObjectCollection.ToList();

    }

    public int FindChildRecords(int? id)

    {

        var count = 0;

        for (var i = 0; i < TreeData.GetSelfDataSource().Count; i++)

        {

            if (TreeData.GetSelfDataSource()[i].ParentId == id)

            {

                count++;

                count += FindChildRecords(TreeData.GetSelfDataSource()[i].TaskId);

            }

        }

        return count;

    }

 

 

    …..

 



Please refer to the attached sample linked below for an example of using custom adapter with Row Drag and Drop:


Kindly get back to us for further assistance.


Regards,
Pon selva


Attachment: Rowdd_with_custom_adapotr_38679c29.zip

Loader.
Up arrow icon