1
votes

I have recently had an issue with Kendo MVC where I have needed to drag a product code from one Kendo Grid into another where the cell value is empty.

Scenario: Grid A, products ordered, where the vendor sending the list of products doesnt have a full product list and 90% accurate descriptions.

Grid B, Products, with full \ correct descriptions and product codes.

I now need to populate Cell x in Grid A, with data from Cell Y in Grid B. In the current windows (WinForms) application, the user can use drag and drop.

Issue: Kendo Grids do not easily provide a drag and drop feature.

Kendo themselves, admittedly a while back say this is not supported but produced a fiddle that would allow the dragging and dropping of a cell to re-order the row, and thats about it.

They also, never produced any scenario for ASP.Net MVC.

1

1 Answers

1
votes

As this is something that I need, and also appears to be something that others may have searched for, you will see below the code in here to help someone who was \ is in my position, and a fiddle for the Kendo UI, and the MVC examples.

Because of how my project is organised and is using Typescript the MVC version isnt going to be 1:1 exact but will be close enough for someone to follow.

A few caveats on this is when you pick up the item, you can click anywhere on the row. (if anyone can refine this please post an answer, I will test and if it works I will upvote and also incorporate your answer with working code.

In addition to the above the dataItem that you pick up is picked up in a position relative to where the mouse is. This I will fix over time, but if anyone gets to this before me please feel free as above.

First,

Kendo UI Code

Html

<html>
<head>
    <title>KendoUI Test Page</title>

<link href="//kendo.cdn.telerik.com/2018.3.1017/styles/kendo.common.min.css" rel="stylesheet" />


    <script src="//code.jquery.com/jquery-1.8.2.min.js"></script>
    <script src="//kendo.cdn.telerik.com/2018.3.1017/js/kendo.all.min.js"></script>
</head>
<body>
    <div id="grid"></div>    
    <div id="grid2"></div>


</body>
</html>

CSS

 .hint {
    padding: 7px 10px;
    background-color: #FFFFFF;
 }

**JavaScript \ JQuery **

var data = [
        { id: 1, text: "text 1", position: 0 },
        { id: 2, text: "text 2", position: 1 },
        { id: 3, text: "text 3", position: 2 }
    ]

var data2 = [
        { id: 4, text: "", position: 0 },
        { id: 5, text: "", position: 1 },
        { id: 6, text: "", position: 2 }
    ]

    var dataSource = new kendo.data.DataSource({
        data: data,        
        schema: {
            model: {
                id: "id",
                fields: {
                    id: { type: "number" },
                    text: { type: "string" },
                    position: { type: "number" }
                }
            }
        }
    });

    var dataSource2 = new kendo.data.DataSource({
        data: data2,        
        schema: {
            model: {
                id: "id",
                fields: {
                    id: { type: "number" },
                    text: { type: "string" },
                    position: { type: "number" }
                }
            }
        }
    });

    var grid = $("#grid").kendoGrid({
        dataSource: dataSource,  
        scrollable: false,    
        columns: ["id", "text"]            
    }).data("kendoGrid");

    var grid2 = $("#grid2").kendoGrid({
        dataSource: dataSource2,  
        scrollable: false,    
        columns: ["id", "text"]            
    }).data("kendoGrid");

    grid.table.kendoDraggable({
        filter: "tbody > tr",
        group: "gridGroup",
        threshold: 100,
        hint: function(e) {
            var dataItem = grid.dataItem(e);
            return $('<div class="hint">' + dataItem.text + '</div>').css({ marginLeft: e.clientX, marginTop: e.clientY });
        }
    });


    grid2.table.kendoDropTarget({
        group: "gridGroup",
        drop: function(e) {        
            e.draggable.hint.hide();

            var dest = $(document.elementFromPoint(e.clientX, e.clientY));
            var row = dest.closest('tr')
            var uid = row[0].dataset.uid
            var originalVal = dest[0].innerHTML
            var target = dataSource2.getByUid(uid)
            var g = $("#grid2").data("kendoGrid")
            $.each(g.dataSource.data(), function(idx, gridrow){
                if(gridrow.uid === uid){
                var dataItem = g.dataSource.get(gridrow.id)
                dataItem.set("text", e.draggable.hint[0].innerHTML);
              }
            })

        }
    });

Fiddle https://jsfiddle.net/SimonPrice/t2aju3c6/77/

MVC 5 Razor Partial

<div class="row">
    <div id="divOrderedLines" class="col-md-6 col-sm-6 col-xs-6" hidden>
        <div class="panel panel-default">
            <div class="panel-heading">OrderedLines</div>
            <div class="panel-body">
                @Html.Partial("_orderedLines")
            </div>
        </div>
    </div>

    <div id="divProductLines" class="col-md-12 col-sm-12 col-xs-12">

        <div class="panel panel-default">
            <div class="panel-heading">Product Lines</div>
            <div class="panel-body">
                @Html.Partial("_productLines")
            </div>
        </div>
    </div>

</div>

Ordered Lines \ Dropping \ Droppable Grid

@(Html.Kendo().Grid<zzzViewModel>
      ()
      .Name("epsGrid")
      .Columns(columns =>
      { 
          //Columns removed 
          columns.Bound(c => c.ProductCode).HtmlAttributes(new { @class = "drop-target" });
      })
      .Events(evt => evt.DataBound("fe_rxManager.SetEpsTableOptions"))
      .Events(evt => evt.Change("fe_rxManager.styleColumn"))
      .Pageable(pageable => pageable
          .Refresh(true)
          .PageSizes(true)
          .ButtonCount(5)
      )
      .ToolBar(toolbar =>
      {
          toolbar.Template(@<text><button id="btnNewOrder" class="btn btn-default" disabled="disabled">New Order <i class="fa fa-plus"></i></button></text>);
      })
        .DataSource(dataSource => dataSource
            .Ajax()
            .Read(read => read.Action("Ordered_Read", "RxManager"))
            .PageSize(20)
        )
)

Product Lines \ Draggable Grid

@(Html.Kendo().Grid<xxxViewModel>
      ()
      .Name("rxGrid")
      .Columns(columns =>
      {
          columns.Bound(c => c.OrderId).Visible(false);
          columns.Bound(c => c.LineID).Visible(false);
          columns.Bound(c => c.ProductCode).HtmlAttributes(new { @class= "product-code" });
          columns.Bound(c => c.Quantity);
          columns.Bound(c => c.CPQuantity);
          columns.Bound(c => c.PQuantity);
          columns.Bound(c => c.Description);
          columns.Bound(c => c.OnHandQuantity);
      })
      .Events(evt => evt.DataBound("fe_rxManager.rxLinesDataChanged"))
      .Pageable(pageable => pageable
          .Refresh(true)
          .PageSizes(true)
          .ButtonCount(5)
      )
      .Editable(m => m.Mode(GridEditMode.InCell).DisplayDeleteConfirmation(false))
      //.BindTo(@Model.xxxLines)
      .DataSource(dataSource => dataSource
                .Ajax()
                .Read(read => read.Action("Product_Read", "RxManager").Data("fe_rxManager.xxxLines_Read_AdditionalData"))
                .Model(model =>
                {
                    model.Id(l => l.xxxLineID);
                    model.Field(p => p.ProductCode).Editable(false);
                    model.Field(p => p.Description).Editable(false);
                    model.Field(p => p.Quantity).Editable(false);
                    model.Field(p => p.CPQuantity).Editable(false);
                    model.Field(p => p.PQuantity).Editable(true);
                    model.Field(p => p.PQuantityPrice).Editable(false);
                    model.Field(p => p.OnHandQuantity).Editable(false);

                })
          .PageSize(20)
      ))

Typscript \ JavaScript \ JQuery

SetEpsTableOptions = (e: any) => {
        this.dragAndDrop();
        this.hideLastColumn(); // Dont worry about this
        this.styleColumn(e);   // Dont worry about this 
    }

    dragAndDrop = () => {

        var rxGrid = $("#rxGrid").data("kendoGrid") as any;
        rxGrid.table.kendoDraggable({
            filter: "tbody > tr",
            group: "gridGroup",
            threshold: 100,
            hint(e) {
                var dataItem = rxGrid.dataItem(e);
                return $('<div class="hint">' + dataItem.ProductCode + '</div>').css({ marginLeft: e.clientX, marginTop: e.clientY });
            }
        });

        var epsGrid = $("#epsGrid").data("kendoGrid") as any;
        epsGrid.table.kendoDropTarget({
            group: "gridGroup",
            drop(e) {
                e.draggable.hint.hide();

                var dest = $(document.elementFromPoint(e.clientX, e.clientY));
                var row = dest.closest('tr');
                var uid = row[0].dataset.uid;
                $.each(epsGrid.dataSource.data(),
                    (idx, gridrow) => {
                        if (gridrow.uid === uid) {
                            var dataItem = epsGrid.dataSource.get(gridrow.id);
                            dataItem.set("ProductCode", e.draggable.hint[0].innerHTML);
                        }
                    });

            }
        });

    }

Hopefully this post can help a few people out. Please feel free to leave positive comments that could either help improve this post.