Submit form with Kendo MVC Grid and other elements

2019-02-03 08:14发布

I am trying to get a Form containing a telekik MVC grid and other elements to submit.

  • The View model contains contains three string fields and an IEnumerable collection.
  • The grid is server bound. I am not adding any elements or deleting any elements from the list using the grid but the grid contains a check box mapped to a boolean column in the list items.

When ever i submit this form the three string elements return in the post method but list is always null.

Here is the data model:

public class Parent
{
    public string Field1{get;set;}
    public string Field2{get;set;}
    public string Comments {get;set;}
    public IEnumerable<ChildItems> Children{get;set;}

}

Public class ChildItems
{
    public string ChildField1{get;set;}
    public string ChildField2{get;set;}
    public boolean Include{get;set;}

}

Here is my View:

@{
    ViewBag.Title = "Index";
}
@model GridInForm.Models.Parent


@using(Html.BeginForm("Save", "Home"))
{
    <fieldset>
        <legend>Editing Parent</legend>

        @Html.LabelFor(parent => parent.Field1)
        @Html.EditorFor(parent => parent.Field1)

        @Html.LabelFor(parent => parent.Field2)
        @Html.EditorFor(parent => parent.Field2)
        @Html.LabelFor(parent => parent.Comments)
        @Html.EditorFor(parent => parent.Comments)
        @(Html.Kendo().Grid(Model.Children)
              .Name("Children")
              .ToolBar(tools => tools.Create().Text("Add new Children"))
              .Editable(editable =>      editable.Mode(GridEditMode.PopUp)
               .CreateAt(GridInsertRowPosition.Bottom))
              .Columns(columns =>
              {
                  columns.Bound(p => p.ChildField1).ClientTemplate("#= ChildField1 #" + 
                    "<input type='hidden' name='ChildField1[#= index(data)#].ChildField1'        
                     value='#= Name #' />"
                  );

                  columns.Bound(p => p.ChildField2).Hidden().ClientTemplate("#= ChildField1
                   #" +
                    "<input type='hidden' name='ChildField1[#= index(data)#].ChildField1' 
                  value='#= ChildField1 #' />"
                  );

                  columns.Command(command => 
                      {
                         // command.Destroy();
                          command.Edit();
                      }
                      ).Width(100);
              })
              .DataSource(dataSource => dataSource.Server().Create("Create", 
              "Home").Read("Index", "Home").Update("Update", "Home")
                   .Model(model => 
                       {
                           model.Id(p => p.ChildField1);
                           model.Field(p => p.ChildField1).Editable(false);
                       })
                   //.ServerOperation(true)
              )
        )
    </fieldset>

    <input type="submit" value="Save" />
}

<script>

function index(dataItem) {
    alert("bindind");
    var data = $("#Products").data("kendoGrid").dataSource.data();

    return data.indexOf(dataItem);
}

</script>

WHen i submit the form I get the parents items back in the view model but the Inumerable fields from the grid are always null..

Is this just not the way to do this and if so what is the way to acommplish something like this. I have had this issue on previous telerik versions and I see it is the same on Kendo UI. Any direction would be greatly appreciated. This has been along going on issue.

3条回答
该账号已被封号
2楼-- · 2019-02-03 08:23

I was inspired by codebeastie and @user1878526 to produce the following hybrid idea - simply returning the grid as a list of strings to the controller save action:

Controller:

Function Save(ThisForum As myModel, gridData As List(Of String)) As ActionResult

View:

$("#myForm").submit(function (event) {
            var grid = $("#myGrid").data("kendoGrid");
            var data = grid.dataSource.view();
            var input;
            for (var i = 0; i < data.length; i++) {
                var s = JSON.stringify(data[i]).replace(/["']/g, "");
                input = $("<input>", { type: 'hidden', name: 'data[' + i + ']', value: s });
                $(this).append($(input));
            }
        })

This can then be parsed in the controller reasonably easily by 'Split'ing on commas and colons.

查看更多
萌系小妹纸
3楼-- · 2019-02-03 08:33

So here is part of a solution to your question. I extended the kendo Datasource, so you can call this function and get all the updated, deleted, created items out. Just turn it into json and send it back with the rest of your form fields. I have got this working now. Thought I would share.

kendo.data.DataSource.prototype.GetUnsavedData = function () {
    var that = this,
        idx,
        length,
        created = [],
        updated = [],
        destroyed = that._destroyed,
    allRows = [],
        data = that._flatData(that._data);

    for (idx = 0, length = data.length; idx < length; idx++) {
        if (data[idx].isNew()) {
            created.push(data[idx]);
        } else if (data[idx].dirty) {
            updated.push(data[idx]);
        }
    }

    allRows = created.concat(updated).concat(destroyed);
    var allRowsJSON = JSON.stringify(allRows);
    return allRowsJSON;
}
查看更多
混吃等死
4楼-- · 2019-02-03 08:34

I have exactly this scenario working perfectly in my project. Here's my grid declaration...

@(Html.Kendo().Grid(Model.ChildLines)
    .Name("RequestLinesGrid")
    .Editable(editable => editable.Mode(Kendo.Mvc.UI.GridEditMode.InCell))
         .Columns(columns =>
         {
             columns.Bound(p => p.ItemCode).ClientTemplate("#= ItemCode #" +
               "<input type='hidden' name='MyLines[#= index(data)#].ItemCode' value='#= ItemCode #' />"
             );
             columns.Bound(p => p.Description).ClientTemplate("#= Description #" +
               "<input type='hidden' name='MyLines[#= index(data)#].Description' value='#= Description #' />"
             );
             columns.Bound(p => p.UoM).ClientTemplate("#= UoM #" +
               "<input type='hidden' name='MyLines[#= index(data)#].UoM' value='#= UoM #' />"
             );
             columns.Bound(p => p.QtyCC).ClientTemplate("#= QtyCC #" +
                "<input type='hidden' name='MyLines[#= index(data)#].QtyCC' value='#= QtyCC #' />"
             );
             columns.Bound(p => p.QtyEmployee).ClientTemplate("#= QtyEmployee #" +
                "<input type='hidden' name='MyLines[#= index(data)#].QtyEmployee' value='#= QtyEmployee #' />"
             );
             columns.Bound(p => p.ItemListLineID).Hidden(true).ClientTemplate("#= ItemListLineID #" +
                "<input type='hidden' name='MyLines[#= index(data)#].ItemListLineID' value='#= ItemListLineID #' />"
             );
             columns.Bound(p => p.ItemListCode).Hidden(true).ClientTemplate("#= ItemListCode #" +
                "<input type='hidden' name='MyLines[#= index(data)#].ItemListCode' value='#= ItemListCode #' />"
             );
             columns.Command(command =>
             {
                 command.Destroy();
             }).Width(200);
         })
    .DataSource(dataSource => dataSource.Ajax()
         .Model(m =>
         {
             m.Id(p => p.ItemCode);
             m.Field(p => p.ItemCode).Editable(false);
             m.Field(p => p.Description).Editable(false);
             m.Field(p => p.UoM).Editable(false);
             m.Field(p => p.QtyCC).Editable(true);
             m.Field(p => p.QtyEmployee).Editable(true);
             m.Field(p => p.ItemListLineID).Editable(false);
             m.Field(p => p.ItemListCode).Editable(false);
         })
         .Batch(true)
         .ServerOperation(false)
         // these are dummy action methods that don't really exist.
         .Update("upd", "upd") 
         .Destroy("del", "del")
         .Create("cre", "cre")
    )
    .Navigatable()
)

Here's the "index" function:

function index(dataItem) {
    var data = $("#RequestLinesGrid").data("kendoGrid").dataSource.data();

    return data.indexOf(dataItem);
}
查看更多
登录 后发表回答