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);
}
}
Related
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
I Have two Kendo Grids (UI for Asp.Net MVC) on my page. The first grid gets results from database using an action method of a controller which is bound at grid initialization(I guess). The second grid should get the results of a column from first grid and pass as parameters to second grid which should pass these to action method of another controller bound to second grid. I tried to use autobind(false) but has no use. Please suggest.
Please try with the below code snippet.
VIEW
#(Html.Kendo().Grid<MvcApplication1.Models.TestModel>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(e => e.ID);
columns.Bound(e => e.Name);
})
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetData", "Home"))
)
.Events(events => events.Change("onChange"))
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Single))
)
#(Html.Kendo().Grid<MvcApplication1.Models.ChildModel>()
.Name("ChildGrid")
.Columns(columns =>
{
columns.Bound(e => e.ChildID);
columns.Bound(e => e.ChildName);
})
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetChildData", "Home").Data("GetData"))
)
)
<script>
var ID = 0;
var Name = "";
function onChange(arg) {
ID = this.dataItem(this.select()).ID;
Name = this.dataItem(this.select()).Name;
$('#ChildGrid').data('kendoGrid').dataSource.read();
$('#ChildGrid').data('kendoGrid').refresh();
}
function GetData() {
return {
ID: ID,
Name: Name
};
}
</script>
CONTROLLER
public ActionResult GetChildData([DataSourceRequest] DataSourceRequest request, int ID, string Name)
{
List<ChildModel> lst = new List<ChildModel>();
if (ID == 0)
{
return Json(lst.ToDataSourceResult(request));
}
string str = ":" + ID + "_" + Name;
lst.Add(new ChildModel() { ChildID = 1, ChildName = "Name1" + str });
lst.Add(new ChildModel() { ChildID = 2, ChildName = "Name2" + str });
lst.Add(new ChildModel() { ChildID = 3, ChildName = "Name3" + str });
return Json(lst.ToDataSourceResult(request));
}
public ActionResult GetData([DataSourceRequest] DataSourceRequest request)
{
List<TestModel> lst = new List<TestModel>();
lst.Add(new TestModel() { ID = 1, Name = "Name1", MyDate = DateTime.Now });
lst.Add(new TestModel() { ID = 2, Name = "Name2", MyDate = DateTime.Now });
lst.Add(new TestModel() { ID = 3, Name = "Name3", MyDate = DateTime.Now });
return Json(lst.ToDataSourceResult(request));
}
MODEL
namespace MvcApplication1.Models
{
public class TestModel
{
public int ID { get; set; }
public string Name { get; set; }
[DataType(DataType.DateTime)]
public DateTime? MyDate { get; set; }
}
public class ChildModel
{
public int ChildID { get; set; }
public string ChildName { get; set; }
}
}
Let me know if any concern.
I have done something like that in my project. I've searched a lot and I finally realize that the solution is creating master and detail grids, the first gird will be the master and the second which get information from the first is detail, in my example is have two grid, one for Sport Branch and the other is for Federation. Federation get information from Sport Branch.
The Sport Branch grid:
<div >
#(Html.Kendo().Grid<SportBranchViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.SportBranchTitle).Title("Title").Width(120);
columns.Command(command => { command.Edit().Text("Edit").UpdateText("OK").CancelText("Cancel");
command.Destroy().Text("Delete");
})
.Width(172);
})
.ToolBar(toolbar => toolbar.Create().Text("Create"))
.Editable(editable =>
{
editable.Mode(GridEditMode.InLine);
editable.DisplayDeleteConfirmation("Are you sure you want to delete");
})
.Scrollable()
.Sortable(sortable => sortable.AllowUnsort(true))
.ClientDetailTemplateId("federationtemplate")
.DataSource(dataSource => dataSource
.Ajax()
.Events(events => events.Error("onError"))
.Model(model => model.Id(p => p.SportBranchID))
.Read(read => read.Action("SportBranch_Read", "BaseData"))
.Update(update => update.Action("SportBranch_Update", "BaseData"))
.Create(create => create.Action("SportBranch_Create", "BaseData"))
.Destroy(destroy => destroy.Action("DeleteSportBranch", "BaseData"))
)
.Events(events => events.DataBound("collapseGrid"))
.HtmlAttributes(new { style = "height:400px;" }))
</div>
the Federation grid:
<script id="federationtemplate" type="text/kendo-tmpl">
#(Html.Kendo().Grid<SportBranchFederationViewModel>()
.Name("grid_#=SportBranchID#")
.Columns(columns =>
{
columns.Bound(p => p.FederationName).Title("Title").Width(200);
columns.Command(command =>
{
command.Edit().Text("Edit").UpdateText("OK").CancelText("Cancel");
command.Destroy().Text("Delete");
})
;
})
.ToolBar(toolbar =>
{
toolbar.Create().Text("Create");
}
)
.Editable(editable =>
{
editable.Mode(GridEditMode.InLine);
editable.DisplayDeleteConfirmation("Are you sure you want to delete?");
})
.Scrollable()
.Sortable(sortable => sortable.AllowUnsort(true))
.Pageable()
.Events( e=> e.DataBound("onDataBoundFederation"))
.DataSource(dataSource => dataSource
.Ajax()
.Events(events => events.Error("onError"))
.Model(model => model.Id(p => p.FederationID))
.Read(read => read.Action("SportBranchFederation_Read", "BaseData", new { sportBranchID = "#=SportBranchID#" }))
.Create(create => create.Action("SportBranchFederation_Add", "BaseData", new { sportBranchID = "#=SportBranchID#" }))
.Update(update => update.Action("SportBranchFederation_Update", "BaseData", new { sportBranchID = "#=SportBranchID#" }))
.Destroy(destroy => destroy.Action("SportBranchFederation_Destroy", "BaseData", new { sportBranchID = "#=SportBranchID#" }))
.PageSize(7)
)
.HtmlAttributes(new { style = "height:250px;" })
.ToClientTemplate()
)
</script>
in the controller:
public ActionResult SportBranchFederation_Read(int sportBranchID , [DataSourceRequest] DataSourceRequest request)
{
var data = _bvaDataService.GetFederations(sportBranchID);
return Json(CreateSportBranchFederationsFromFederations(data.ToList()).ToDataSourceResult(request));
}
Here is the steps:
put the second grid in a script tag and specify an id for the script tag.
In the first grid use the ClientDetailTemplateId() and pass the id of script tag which enclose the second grid.
In the action of second grid which you want pass the value of a column of the first gird use the expression "#= [column's name of the first grid]#" (here is "#=SportBranchID#"). Note the "#= #" can use in grid to use a value of a field from the current grid or another. I send this field to my read action to get the corresponding result( look at my controller)
adding ToClientTemplate() to the second grid
read these samples too :
http://demos.telerik.com/kendo-ui/grid/detailtemplate ,
http://demos.telerik.com/aspnet-mvc/grid/detailtemplate
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;
}
}
I created a Create Action in Controller for saving new product into database. I saved it already but when I click Refresh button, it didn't save on Kendo Grid, either database.
public ActionResult Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ProductDTO> products)
{
var results = new List<ProductDTO>();
if (products != null && ModelState.IsValid)
{
foreach (var product in products)
{
var create = db.Products.First(c => c.ProductID == product.ProductID);
results.Add(product);
db.SaveChanges();
}
}
return Json(results.ToDataSourceResult(request, ModelState));
}
EDIT
Kendo View:
#(Html.Kendo().Grid(Model)
.Name("Products")
.Columns(c =>
{
c.Command(p => p.Edit()).Width(170);
c.Bound(p => p.ProductID);
c.Bound(p => p.Name);
c.Bound(p => p.ListPrice);
c.Bound(p => p.ProductNumber);
c.Bound(p => p.Color);
c.Bound(p => p.StandardCost);
c.Command(p => p.Destroy()).Width(100);
}
)
.ToolBar(tb =>
{
tb.Create();
tb.Save();
})
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Sortable()
.Editable(e => e.Mode(GridEditMode.InCell))
.DataSource(d => d .Ajax()
.Batch(true)
.Model(model =>
{
model.Id(c => c.ProductID);
})
.Create("Create", "Home")
.Read("GetSub","Home")
.Update("Edit", "Home")
.Destroy("Delete", "Home")
.PageSize(10)
)
.HtmlAttributes(new { style= "width: 800px" })
)
What's a solution could be solve in this case? Thank you for your reply, have a great day!
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"
}