Telerik Kendo UI Grid MVC - Programmatically Cancel Edits - kendo-ui

During editing of the grid, I need to validate the data input and if it fails validation, I need to revert the bad data back to an unchanged state so it won't get saved (akin to using the Reset button, but just for the current row being editing...this is a batch editing grid).
Using the javascript code below, I can identify the problem, throw up the alert, but after the user accepts the alert, they could still just click the Save button and it would save that way, with the incorrect data.
To combat this, you'll see I try to set the e.values and e.model to 0, but it is not working (no error is thrown, it just doesn't change the value in the grid).
Maybe I need to identify the DOM element and change it's value directly, but I couldn't find how to retrieve the DOM element from the e object.
function beforeCartonPackUpdates(e) {
if (e.values.QtyToPack > e.model.OrderedQty) {
alert("ERROR! You cannot pack more than was ordered.");
e.model.set("QtyToPack", 0);
e.values.QtyToPack = 0;
return false;
}
if (e.values.QtyToPack > e.model.RemainingToPack) {
alert("Warning! You are packing more than is available.");
return true;
}
}
#(Html.Kendo().Grid<OTIS.AppServ.OrderMgmt.ViewModels.ShipOrderDetailViewModel>()
.Name("ShipOrderDtlsGrid")
.HtmlAttributes(new { style = "width:100%;" })
.Resizable(resize => resize.Columns(true))
.Columns(columns =>
{
columns.Bound(l => l.Id).Hidden();
columns.Bound(l => l.OrderHeaderId).Hidden();
columns.Bound(l => l.StatusId).Hidden();
columns.Bound(l => l.ItemId)
.ClientTemplate("<a href='" +
Url.Action("Edit", "ManageItems", new { area = "InventoryMgmt" }) +
"/#= ItemId #'" +
" target='_blank'>#= ItemDescription #</a>"
)
.ClientFooterTemplate("#=kendo.format('Line Count: {0:n0}', count)#");
columns.Bound(l => l.OrderedQty)
.Title("Ord")
.HeaderHtmlAttributes(new { style = "text-align:right;" })
.HtmlAttributes(new { style = "text-align:right;" })
.FooterHtmlAttributes(new { style = "text-align:right;" })
.ClientFooterTemplate("#=kendo.format('{0:n2}', sum)#");
columns.Bound(l => l.BackorderedQty)
.Title("B/O")
.HeaderHtmlAttributes(new { style = "text-align:right;" })
.HtmlAttributes(new { style = "text-align:right;" })
.FooterHtmlAttributes(new { style = "text-align:right;" })
.ClientFooterTemplate("#=kendo.format('{0:n2}', sum)#");
columns.Bound(l => l.PickedQty)
.Title("Pick")
.HeaderHtmlAttributes(new { style = "text-align:right;" })
.HtmlAttributes(new { style = "text-align:right;" })
.FooterHtmlAttributes(new { style = "text-align:right;" })
.ClientFooterTemplate("#=kendo.format('{0:n2}', sum)#");
columns.Bound(l => l.PackedQty)
.Title("Pack")
.HeaderHtmlAttributes(new { style = "text-align:right;" })
.HtmlAttributes(new { style = "text-align:right;" })
.FooterHtmlAttributes(new { style = "text-align:right;" })
.ClientFooterTemplate("#=kendo.format('{0:n2}', sum)#");
columns.Bound(l => l.RemainingToPack)
.Title("Remain")
.HeaderHtmlAttributes(new { style = "text-align:right;" })
.HtmlAttributes(new { style = "text-align:right;" })
.FooterHtmlAttributes(new { style = "text-align:right;" })
.ClientFooterTemplate("#=kendo.format('{0:n2}', sum)#");
columns.Bound(l => l.QtyToPack)
.HeaderHtmlAttributes(new { style = "text-align:right;" })
.HtmlAttributes(new { #class = "editable", style = "text-align:right;" })
.FooterHtmlAttributes(new { style = "text-align:right;" })
.ClientFooterTemplate("#=kendo.format('{0:n2}', sum)#");
//columns.Command(command =>
// {
// command.Edit();
// command.Destroy();
// }).Width(180);
})
.Editable(editing => editing.Mode(GridEditMode.InCell))
.Events(events =>
{
//events.SaveChanges("afterCartonPackUpdates"); //fires BEFORE saving - good place to do validation
events.Save("beforeCartonPackUpdates"); //fires Before saving, but as soon as cell value changes, better place to do validation
events.SaveChanges("preCartonPackUpdates");//fires AFTER .Save but before calling destroy method
}
)
// Add "Create" command
.ToolBar(toolbar =>
{
//toolbar.Create().Text("Add Work Order Detail");
toolbar.Template(#<text>#RenderOrderDetailsToolBar()</text>);
//toolbar.Custom().Text("<span class='k-icon k-cancel'></span>Cancel</text>").Url("##_").HtmlAttributes(new { #class = "k-grid-cancel-changes" });
//toolbar.Custom().Text("<span class='k-icon k-update'></span>Pack</text>").Url("##_").HtmlAttributes(new { #class = "k-grid-save-changes" });
//toolbar.Save();
})
.DataSource(dataSource => dataSource
.Ajax() // Specify that the data source is of ajax type
.Aggregates(aggregates =>
{
aggregates.Add(x => x.ItemId).Count();
aggregates.Add(x => x.OrderedQty).Sum();
aggregates.Add(x => x.PickedQty).Sum();
aggregates.Add(x => x.RemainingToPack).Sum();
aggregates.Add(x => x.QtyToPack).Sum();
aggregates.Add(x => x.PackedQty).Sum();
aggregates.Add(x => x.BackorderedQty).Sum();
})
.Batch(true)
.Model(model =>
{
model.Id(c => c.Id);
model.Field(c => c.OrderHeaderId).DefaultValue(Model.Id);
model.Field(c => c.UnitCost).Editable(false);
model.Field(c => c.ItemDescription).Editable(false);
model.Field(c => c.OrderedQty).Editable(false);
model.Field(c => c.PickedQty).Editable(false);
model.Field(c => c.PackedQty).Editable(false);
model.Field(c => c.BackorderedQty).Editable(false);
}
)
.Sort(sort =>
{
sort.Add(c => c.ItemDescription);
})
.Events(events =>
{
events.Error("KendoGridErrors");// Specify a handler for the error event
events.RequestEnd("onPackCartonGridComplete");
}
)
// CRUD configuration -->
//.Create(create => create.Action("Grid_SaveOrUpdate", "ManageWorkOrders", new { area = "OrderMgmt" }).Type(HttpVerbs.Post))
.Read(read => read.Action("GetShipOrderDetails", "ManageShipOrders", new { area = "OrderMgmt", intOrderHeaderId = #Model.Id })// Specify the action method and controller name
.Type(HttpVerbs.Get)
)
.Update(update => update.Action("CreateCartonAndPack", "ManageShippingContainers", new { area = "OrderMgmt" }).Type(HttpVerbs.Post))
//.Destroy(destroy => destroy.Action("Grid_Delete", "ManageWorkOrders", new { area = "OrderMgmt" }).Type(HttpVerbs.Post))
// <-- CRUD configuration
)
.Sortable()
)

Figured it out...was simple in the end. Just needed to put in the e.preventDefault();
function shipOrderDtlsGrid_OnSave(e) {
if (e.values.QtyToPack > e.model.RemainingToPack) {
e.preventDefault();
alert("ERROR! You cannot pack more than is Remaining To Pack.");
return;
}
}

Related

How to get querystring value to Kendo Grid update method and pass to MVC controller

I have a kendo grid and need to get a querystring value. See below code.
Browser Url = http://blahblah/blah/36?EvaluationCriteriaGrid-mode=edit&chiefEvalCriteriaId=110
UI.cshtml
#(Html.Kendo().Grid(Model.ChiefEvaluationCriteriaList.AsEnumerable())
.Name("EvaluationCriteriaGrid")
.Columns(columns =>
{
columns.Bound(p => p.EvaluationCriteriaName);
columns.Bound(p => p.MinScore).Width(100).Title("Min Score").Format("{0:0}");
columns.Bound(p => p.MaxScoreDisplay).Width(100).Title("Max Score");
columns.Command(command => { command.Edit(); }).Width(180).Title("Action");
})
.CellAction(cell =>
{
if (cell.Column.Title == "Action")
{
if (cell.DataItem.EvaluationResultID ==
ServiceProxy.Model.DomainConstants.EVALUATION_RESULT_APPROVED)
{
cell.HtmlAttributes["style"] = "display:none;";
}
}
})
.Editable(editing => editing.Mode(GridEditMode.InLine))
.Pageable()
.Sortable()
.Scrollable()
.DataSource(dataSource => dataSource
.Server()
.Model(model => model.Id(c => c.ChiefEvaluationCriteriaID))
.Read("EvaluationQuestionnaire", "EvaluationCriteria", new { area = "Proposal", Id = Model.SolicitationDetails.SolicitationID })
.Update("EditEvaluationCriteria", "EvaluationCriteria", new { area = "Proposal", Id = Model.SolicitationDetails.SolicitationID })
)
)
Controller.cs
[HttpPost]
public ActionResult EditEvaluationCriteria( int Id, int chiefEvalCriteriaId, int maxScoreDisplay, int minScoreDisplay = 0 )
{
if (ModelState.IsValid)
{
Do something
}
return view
}
Thank you for the support

Kendo Grids ClientTemplate for ForeignKey column not displaying chosen value?

Using MVC, I am trying to implement inline-editing of a Kendo Grid using a Foreign Key Column...which should display & save a chosen value from it's relevant ComboBox.
Editing works...but it doesn't display the chosen value upon UPDATING the row.
What am I doing wrong?
MY VIEW CONTROL LOOKS LIKE:
#(Html.Kendo().Grid<RTUDeviceCustomRegisterModbus>()
.Columns(columns =>
{
columns.Bound(x => x.Id)
.Visible(false);
columns.Bound(x => x.RTUDeviceId)
.Visible(false);
columns.Bound(x => x.Register)
.Title("Register")
.Width(50);
columns.Bound(x => x.Description)
.Title("Description")
.Width(100);
columns.ForeignKey(x => x.DataUnitId, Model.DataUnits, "Id", "DataUnitName")
.ClientTemplate((#Html.Kendo().ComboBox()
.BindTo(Model.DataUnits)
.Name("ddlDataUnits_#=Id#")
.DataValueField("Id")
.DataTextField("DataUnitName")
.ToClientTemplate()).ToHtmlString())
.Title("Units")
.Width(50);
columns.ForeignKey(x => x.DataTypeId, Model.DataTypes, "Id", "DataTypeName")
.Title("Data Type")
.Width(50);
columns.Bound(x => x.DataTypeSize)
.Title("ASCII (size)")
.Width(50);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(100);
})
.Name("gridCustomRegisterModbus")
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Sortable()
.Scrollable()
.BindTo(Model.RTUDeviceCustomRegisterModbuses)
.DataSource(dataSource => dataSource.Ajax()
.ServerOperation(true)
.PageSize(50)
.Model(model => { model.Id(m => m.Id); })
.Create(update => update.Action("Create", "CustomRegisterModbus", new { Area = "Documents" }))
.Update(update => update.Action("Update", "CustomRegisterModbus", new { Area = "Documents" }))
.Destroy(update => update.Action("Destroy", "CustomRegisterModbus", new { Area = "Documents" }))
)
.HtmlAttributes(new { #class = "", #style = "height: 400px;" }))
MY ACTION LOOKS LIKE:
Yes, it calls the action...but the DataUnitId is NULL. So, I am guessing I need the client template for that part...but that isn't working.
public class CustomRegisterModbusController : BaseController
{
#region <Actions>
[HttpPost]
public ActionResult Create([DataSourceRequest] DataSourceRequest request, RTUDeviceCustomRegisterModbus entity)
{
// It makes the call to CREATE...but the value of the ID is null
return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
}
[HttpPost]
public ActionResult Update([DataSourceRequest] DataSourceRequest request, RTUDeviceCustomRegisterModbus entity)
{
// Do awesome stuff
return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
}
[HttpPost]
public ActionResult Destroy([DataSourceRequest] DataSourceRequest request, RTUDeviceCustomRegisterModbus entity)
{
// Do awesome stuff
return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
}
#endregion
}
I hate to answer my own question, but here it is...
I needed a client-side method to handle Grid.Save
This method would sets any chosen DROP DOWN LIST value into the model
I tried all kinds of other posted solutions...this is the ONLY thing that worked.
THE FINAL RAZOR MARKUP LOOKS LIKE:
#(Html.Kendo().Grid<RTUDeviceCustomRegisterModbus>()
.Columns(columns =>
{
columns.Bound(x => x.Id)
.Visible(false);
columns.Bound(x => x.RTUDeviceId)
.Visible(false);
columns.Bound(x => x.Register)
.Title("Register")
.Width(50);
columns.Bound(x => x.Description)
.Title("Description")
.Width(100);
columns.ForeignKey(x => x.DataUnitId, Model.DataUnits, "Id", "DataUnitName")
.Title("Units")
.Width(50);
columns.ForeignKey(x => x.DataTypeId, Model.DataTypes, "Id", "DataTypeName")
.Title("Data Type")
.Width(50);
columns.Bound(x => x.DataTypeSize)
.Title("ASCII (size)")
.Width(50);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(100);
})
.Name("gridCustomRegisterModbus")
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Sortable()
.Scrollable()
.BindTo(Model.RTUDeviceCustomRegisterModbuses)
.DataSource(dataSource => dataSource.Ajax()
.ServerOperation(true)
.PageSize(50)
.Model(model => { model.Id(m => m.Id); })
.Create(update => update.Action("Create", "CustomRegisterModbus", new { Area = "Documents" }))
.Update(update => update.Action("Update", "CustomRegisterModbus", new { Area = "Documents" }))
.Destroy(update => update.Action("Destroy", "CustomRegisterModbus", new { Area = "Documents" }))
)
.HtmlAttributes(new { #class = "", #style = "height: 400px;" }))
THE JAVASCRIPT METHOD LOOKS LIKE:
Of course, you will probably put the method in your own 'controller' class
If you use Razor to bind to the GRIDS event...
.Events(events => events.Save("onSave"))
If you use a Custom JavaScript Controller to bind the event...
// Instances
var grid = $('#mygrid').data('kendoGrid');
// Bindings
grid.bind('save', onSave);
// Of course you would point to a custom Object
function onSave(e) {
var model = e.model;
var ddl = null;
var text = null;
// DataUnits
ddl = $(e.container.find('[data-role=dropdownlist]')[0]).data('kendoDropDownList');
text = ddl.value();
if (text !== null && text.length > 0) {
//model.DataUnitId = 0;
model.set('DataUnitId', text);
}
// DataTypes
ddl = $(e.container.find('[data-role=dropdownlist]')[1]).data('kendoDropDownList');
text = ddl.value();
if (text !== null && text.length > 0) {
//model.DataTypeId = 0;
model.set('DataTypeId', text);
}
}

How to get row values in Kendo Grid before inline deletion

I have been using inline deletion for Kendo Grid, but I need to check the conditions and then delete the rows.
#(Html.Kendo().Grid<DocumentSearchViewModel>()
.Name("documentListGrid")
.Columns(columns =>
{
columns.Bound(model => model.AgentID).Title("Agent Code").Width("15%");
columns.Bound(model => model.DocumentSecurityID).ClientTemplate("#if(data.AllowToView==1)" +
"{ #<a class='lnkDocument' href='" + Url.Action("Download", "Document", new { fileName = "#=ScanFile#", fileLocation = "#=VC01#", batchTime = "#=BatchTime#", documentNumber = "#=CaseID#" }) + "' target='documentViewer'>#=data.BatchDescription#</a>#" +
" " + " }" +
"else{#<a class='disable-link' onclick='return Response();'>#=data.BatchDescription#</a> #}#").Title("Description").Width("30%");
columns.Bound(model => model.CaseID).Width("10%").Title("Case#");
columns.Bound(model => model.DocumentGroupID).Width("15%").Title("Group ID");
columns.Bound(model => model.BatchNumber).Width("10%").Title("Batch#");
columns.Bound(model => model.CreatedDate).Width("10%").Format(UI.DocumentSearchDateFormat).Title("Created Date");
columns.Command(command => command.Custom("Remove").Click("deleteRow"));
columns.Bound(model => model.DocSystemID).Visible(false);
})
.Pageable()
.Sortable(sortable => sortable.AllowUnsort(false))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Model(model => model.Id(p => p.CaseID))
.Read(read => read.Action(WorkflowControllers.Document.ActionNames.GetDocumentList, WorkflowControllers.Document.Name, new { caseId = #Model.CaseID }))
.Events(ev => ev.Change("OnGridChange"))
).AutoBind(true).Events(events => events.DataBound("DisplayDocument"))
)
Calling javascript function which will call a Controller method using Ajax Call:
function deleteRow(e) {
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var grid = $("#documentListGrid").data("kendoGrid");
if (confirm("Are you sure you want to delete the selected record(s)?")) {
grid.removeRow($(e.target).closest("tr"));
} else {
// cancel button is clicked
}
}
How do I get the row's value and check the conditions?
$('#Grid').click(function () {
var gview = $(this).data("kendoGrid");
var selectedItem = gview.dataItem(gview.select());
var Guid = selectedItem.YourPropertName;
})
selectedItem will have all the properties of your model

Wrong behavior when try to insert and delete from details kendo grid

I have master and details kendo grid, when I insert/delete the header everything is working fine, but When i try to insert more than one record in the details grid the create statement will loop for all inserted records (new and old ones) each time I try to add a new record, also when I try to delete a record from the details table, the view will call the create method instead of delete one.
#(Html.Kendo().Grid(Model.ItemSuppliers)
.Name("CreateItem_gridSuppliers")
.Columns(columns =>
{
columns.Bound(p => p.ItemCode).Title(MyResources.GridItemCode).Width(100);
columns.ForeignKey(p => p.SupplierID, Model.Suppliers, "SupplierID", "SupplierID").Title(MyResources.Supplier).Width(200).EditorTemplateName("SupplierForeignkeyEditor");
columns.Bound(p => p.SupplierNameE).Title(MyResources.SupplierNameE).Width(150);
columns.Bound(p => p.CustomDutyPercentage).Title(MyResources.CustomDutyPercentage).Width(200);
columns.Bound(p => p.CustomDutyRate).Title(MyResources.CustomDutyRate).Width(200);
columns.Command(command => { command.Edit().Text(MyResources.EditText).UpdateText(MyResources.UpdateText).CancelText(MyResources.CancelText); command.Destroy().Text(MyResources.Delete); }).Width(170);
})
.ToolBar(toolBar =>
{
toolBar.Create().Text(MyResources.AddNewItem);
})
.Events(e => e.Edit("gridEdit").Cancel("OnCancel").DataBound("CreateItem_gridSuppliers_GridDataBound").Change("ItemSupplierSaved"))
.Editable(editable => editable.Mode(GridEditMode.InLine))
.ClientDetailTemplateId("template")
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(5)
.ServerOperation(true)
.Events(events => events.Error("gridErrorHandler"))
.Events(ev => ev.RequestEnd("ItemSupplierSaved"))
.Model(model =>
{
model.Id(p => p.ItemSuppliersID);
model.Field(p => p.ItemSuppliersID).Editable(false);
model.Field(p => p.ItemCode).Editable(false);
})
.Read(read => read.Action("GetItemSuppliers", "Item", new { __cnv = Model.ConversationKey }))
.Update(update => update.Action("ItemSupplier_Update", "Item", new { __cnv = Model.ConversationKey }))
.Create(create => create.Action("ItemSupplier_Create", "Item", new { __cnv = Model.ConversationKey }))
.Destroy(destroy => destroy.Action("ItemSupplier_Delete", "Item", new { __cnv = Model.ConversationKey }))
))
<script id="template" type="text/kendo-tmpl">
#(Html.Kendo().Grid(Model.ItemOrigins)
.Name("ItemOrigin_#=ItemSuppliersID#")
.Columns(columns =>
{
columns.Bound(p => p.ItemCode).Hidden();
columns.Bound(p => p.ItemSuppliersID).Title(MyResources.ItemSuppliersID).Width(120);
columns.Bound(p => p.ItemOriginID).Title(MyResources.ItemOriginID).Width(100);
columns.ForeignKey(p => p.OriginID, Model.Origins, "OriginID", "OriginNameE").Title(MyResources.OriginID).Width(100);
columns.Bound(p => p.ProductBarCode).Title(MyResources.ProductBarCode).Width(200);
columns.Command(command => { command.Edit().Text(MyResources.EditText).UpdateText(MyResources.UpdateText).CancelText(MyResources.CancelText); command.Destroy().Text(MyResources.Delete); }).Width(190);
})
.ToolBar(toolBar =>
{
toolBar.Create().Text(MyResources.AddNewItem);
})
.Events(e => e.Edit("RemoveItemOriginFilter").Cancel("ReloadGrid"))
.Editable(editable => editable.Mode(GridEditMode.InLine).DisplayDeleteConfirmation(true).DisplayDeleteConfirmation(MyResources.ItemOriginDeleteConfirm))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(5)
.ServerOperation(true)
.Events(events => events.Error("gridErrorHandler"))
.Model(model =>
{
model.Id(p => p.ItemOriginID);
model.Field(p => p.ItemOriginID).Editable(false);
model.Field(p => p.ItemSuppliersID).Editable(false);
model.Field(p => p.Origin);
})
.Read(read => read.Action("GetItemOrigin", "Item", new { itemSupplierID = "#=ItemSuppliersID#", __cnv = Model.ConversationKey }))
.Update(update => update.Action("ItemOrigin_Update", "Item", new { itemSupplierID = "#=ItemSuppliersID#", __cnv = Model.ConversationKey }))
.Create(create => create.Action("ItemOrigin_Create", "Item", new { itemSupplierID = "#=ItemSuppliersID#", __cnv = Model.ConversationKey }))
.Destroy(destroy => destroy.Action("ItemOrigin_Delete", "Item", new { itemSupplierID = "#=ItemSuppliersID#", __cnv = Model.ConversationKey }))
)
.ToClientTemplate()
)
</script>
And here is my controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ItemOrigin_Create([DataSourceRequest] DataSourceRequest request, ItemOriginViewModel item, int itemSupplierID, string __cnv)
{
List<ItemOriginViewModel> itemOrigins = new List<ItemOriginViewModel>();
if (Session["ItemOrigin_" + __cnv + itemSupplierID] != null)
{
itemOrigins = (List<ItemOriginViewModel>)Session["ItemOrigin_" + __cnv + itemSupplierID];
if (item.UID == null)
{
item.UID = Guid.NewGuid().ToString();
item.ItemSuppliersID = itemSupplierID;
itemOrigins.Add(item);
}
else
{
int index = itemOrigins.FindIndex(x => x.UID == item.UID);
itemOrigins[index] = item;
}
}
else
{
item.UID = Guid.NewGuid().ToString();
item.ItemSuppliersID = itemSupplierID;
itemOrigins.Add(item);
}
Session["ItemOrigin_" + __cnv + itemSupplierID] = itemOrigins;
return Json(itemOrigins.ToDataSourceResult(request));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ItemOrigin_Delete([DataSourceRequest] DataSourceRequest request, ItemOriginViewModel item, string __cnv)
{
List<ItemOriginViewModel> itemOrigins = (List<ItemOriginViewModel>)Session["ItemOrigin_" + __cnv + item.ItemSuppliersID];
int index = itemOrigins.FindIndex(x => x.ItemOriginID == item.ItemOriginID);
itemOrigins.RemoveAt(index);
Session["ItemOrigin_" + __cnv + item.ItemSuppliersID] = itemOrigins;
var result = itemOrigins;
return Json(result.ToDataSourceResult(request));
}
Any suggestion please to solve this issue??
The Kendo DataSource will attempt to send items that are marked as 'new' or 'dirty'. 'New' just means that the item ID (it looks like your ID column is ItemSuppliersID) is undefined or 0. It will keep resending these items as long as that ID is not set.
Normally, your controller should return the item that was just inserted, but with the ID now set to the new value. Then Kendo will copy the ID from the response to the object on the client. Since the ID is then set, the item will no longer be marked 'new' and will stop being sent to the server.
In other words, if you POST:
{
"ItemSuppliersID": 0,
"ItemCode": "ABC"
}
then the controller should return:
{
"ItemSuppliersID": 123, // <-- ID field is now set
"ItemCode": "ABC"
}

send data to server with data() in kendo ui Grid

how can I send data to server with data() in kendo ui Grid when i have an Ienumerable parameter
I can't send data for " IEnumerable selectedNodeGroupClass " in Read function
Grid in View
#(Html.Kendo().Grid<UserProtocol>()
.Name("UserProtocol")
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(15)
.Model(model => model.Id(m => m.tblProtocolID))
.Destroy(destroy => destroy.Action(MVC.Protocol.ActionNames.GridRowDelete, MVC.Protocol.Name))
.Read(read => read.Action(MVC.Protocol.ActionNames.ReadProtocols, MVC.Protocol.Name).Data("additionalData"))
)
.Columns(columns =>
{
columns.Template(#<text></text>).ClientTemplate("#= renderNumber(tblProtocolID)#").Width(30).HeaderTemplate(#<text><input type="checkbox" id="SelectAllCheckBox" value="false" /></text>);
columns.Bound(m => m.dateFrom).Title("تاریخ شروع");
columns.Bound(m => m.dateTo).Title("تاریخ پایان");
columns.Bound(m => m.isActive).Title("وضعیت").ClientTemplate("# if (isActive) { #" + "فعال" + "# } else { #" + "غیر فعال" + "# } #");
columns.Bound(m => m.fName).Title("نام");
columns.Bound(m => m.lName).Title("نام خانوادگي");
columns.Bound(m => m.shomarShenasname).Title("شماره شناسنامه");
columns.Bound(m => m.nationalCode).Title("کد ملی");
columns.Bound(m => m.fatherName).Title("نام پدر");
columns.Bound(m => m.isMale).Title("جنسيت").ClientTemplate("# if (isMale == true) { #" + "مرد" + "# } else { #" + "زن" + "# } #");
columns.Bound(m => m.birthDate).Title("تاريخ تولد");
columns.Template(#<text></text>).Width(40)
.ClientTemplate(Html.ActionLink(" ", MVC.Protocol.ActionNames.UpdateProtocol, new { tblProtocolID = "#= tblProtocolID #" }, new { #class = "tablectrl_small bBlue tipS edit MyCustomAddBtn" }).ToHtmlString());
columns.Template(#<text></text>).ClientTemplate(#"<a href=""\#"" class=""k-button-icontext tablectrl_small bRed tipS Remove MyCustomAddBtn"" data-id='#= tblProtocolID #' />").Width(40);//k-grid-delete
})
.Sortable()
.Pageable(p => p.Messages(x =>
{
x.Display("تعداد {0} - {1} از {2}");
x.Empty("اطلاعاتی برای نمایش در دسترس نیست.");
x.First("صفحه اول");
x.Last("صفحه آخر");
x.Previous("صفحه قبل");
x.Next("صفحه بعد");
x.ItemsPerPage("مورد");
x.Of("از");
x.Page("صفحه");
}))
.Scrollable()
.Editable(editable => editable.DisplayDeleteConfirmation(false))
//.Events(ev => ev.DataBound("resetRowNumber"))
.HtmlAttributes(new { style = "Height:430px; border-width:0px" })
.ToolBar(toolbar => toolbar.Template("<input id=\"DeleteAll\" type=\"button\" value=\"حذف انتخاب شده ها\" class=\"k-button\" />"))
)
Read function in my controller
[HttpPost]
public virtual JsonResult ReadProtocols([DataSourceRequest] DataSourceRequest request, UserProtocol userProtocol = null, IEnumerable<Test> selectedNodeGroupClass = null)
{
}
Test class :
public class Test
{
public string ID { get; set; }
public bool IsSelect { get; set; }
}
and data() function in jquery is
function additionalData() {
////Define a class
function Test(id, isSelect) {
this.ID=id,
this.IsSelect=isSelect
}
var arr = new Array();
$('#sidebarmenu1 input:checkbox').each(function () {
var value;
var checked = false;
if ($(this).is(":checked")) {
checked = true;
}
value = $(this).parent().parent().parent().find("input:hidden").first().val();
var s = new Test(value, checked);
arr.push(s);
});
var strAr = JSON.stringify(arr);
debugger;
return {
selectedNodeGroupClass:arr,
dateFrom: $("#dateFrom").val(),
dateTo: $("#dateTo").val(),
nationalCode: $("#nationalCode").val(),
shomarShenasname: $("#shomarShenasname").val(),
fName: $("#fName").val(),
lName:$("#lName").val(),
};
}
The default MVC Model binder requeres special format in which the data form collection should be composed. The whole magic is discussed in this forum thread. You can get a generic function that handles that 'transforming' of the JavaScript array from this code library which shows how the multiselect collection of objects is send to the server.

Resources