I posted this query as a support ticket but I'm hoping to get an answer before the weekend is over.
I have a Grid with batch editing enabled. It also features a custom toolbar with an additional button: 'Archive'.
Users will be able to check multiple rows and click the 'Archive' button in the toolbar.
The button should submit all the selected rows (models) and POST them to a server side method for processing.
I have used this post as a basis for my work:
https://www.telerik.com/forums/how-to-pass-a-grid%27s-selected-row-values-to-controller
In the post, the custom button simply gets the selected items and posts them to the appropriate Controller method.
I need to POST an IEnumerable<T> to the Controller. Not just properties of an object.
I keep getting this error message:
"Javascript error: 'Uncaught TypeError: Cannot read properties of undefined (reading 'field')'
or the Controller gets NULL.
markup:
<div class="container-fluid"><div class="fc-day-grid-container">
@(Html.Kendo().Grid<Core.Resources.EmPowerReconciliationDto>
()
.Name("EmpFSRollGrid")
.Columns(columns =>
{
columns.Select().Width(50)
.ClientHeaderTemplate("<input type='checkbox' id='selectAll' class='k-checkbox' onClick='selectAll(this)'/>" +
"<label for='selectAll'> All</label>").HeaderHtmlAttributes(new { @class = "k-header" });
columns.Bound(c => c.ProjMessage).Width(100);
columns.Bound(c => c.ProjectId).Width(150);
columns.Bound(c => c.ElectricUtilityUtilityName).Width(150);
columns.Bound(c => c.GasUtilityUtilityName).Width(150);
columns.Bound(c => c.PrimaryHeatingFuel).Width(100);
columns.Bound(c => c.ReferralSF).Width(100);
columns.Bound(c => c.MeasureType).Width(100);
columns.Bound(c => c.ProgramName).Width(100);
columns.Bound(c => c.MeasureId).Width(100);
columns.Bound(c => c.FundedAmount).Width(100).Format("{0:n}").HtmlAttributes(new { @class = "k-text-right" });
columns.Bound(c => c.Adj).Width(100).Format("{0:n}").HtmlAttributes(new { @class = "k-text-right" });
columns.ForeignKey(c => c.XFundingSourceId, (System.Collections.IEnumerable)ViewData["fundingsource"], "FundingSourceId", "FundingSourceDesc").Width(160).Title("Funding Source");
columns.Bound(c => c.MeasureCategoryMeasureCategoryDesc).Width(100);
columns.Bound(c => c.ProjectStage).Width(100);
})
.ToolBar(toolbar =>
{
toolbar.ClientTemplateId("GridToolbarTemplate");
})
.Excel(excel => excel
.FileName($"EmPowerReconciliationReport{System.DateTime.Now.ToString("yyyyMMMMdd")}.xlsx")
.Filterable(true)
.AllPages(true)
)
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable(pageable =>
{
pageable.Refresh(true);
pageable.PageSizes(new[] { 10, 20, 50 });
})
.Sortable()
.Filterable(ftb => ftb.Mode(GridFilterMode.Row))
.Scrollable(s => s.Enabled(true))
.Resizable(resize => resize.Columns(true))
.PersistSelection()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(emp => emp.MeasureId);
model.Field(emp => emp.ProjMessage).Editable(false);
model.Field(emp => emp.ProjectId).Editable(false);
model.Field(emp => emp.ElectricUtilityUtilityName).Editable(false);
model.Field(emp => emp.GasUtilityUtilityName).Editable(false);
model.Field(emp => emp.PrimaryHeatingFuel).Editable(false);
model.Field(emp => emp.ReferralSF).Editable(false);
model.Field(emp => emp.MeasureType).Editable(false);
model.Field(emp => emp.ProgramName).Editable(false);
model.Field(emp => emp.MeasureId).Editable(false);
model.Field(emp => emp.FundedAmount).Editable(false);
model.Field(emp => emp.Adj).Editable(true);
model.Field(emp => emp.XFundingSourceId).Editable(true);
model.Field(emp => emp.MeasureCategoryMeasureCategoryDesc).Editable(false);
model.Field(emp => emp.ProjectStage).Editable(false);
})
.ServerOperation(false)
.Batch(true)
.Events(events => events.Error("error_handler"))
.Events(events => events.RequestEnd("request_end"))
.Read(read => read.Action("GetAllFsRollup", "EmPowerReconciliation"))
.Update(update => update.Action("UpdateCompositeInvoice", "EmPowerReconciliation"))
//.Create(create => create.Action("AddInvoice", "EmPowerInvoiceReport"))
//.Destroy(destroy => destroy.Action("DeleteInvoice", "EmPowerInvoiceReport"))
)
)
</div></div><script id="GridToolbarTemplate" type="text/x-kendo-template">
<div class="toolbar">
<a role="button" class="k-button k-button-icontext k-grid-excel" href="\\#"><span class="k-icon k-i-file-excel"></span>Export to Excel</a>
<a role="button" class="k-button k-button-icontext k-grid-save-changes" href="\\#"><span class="k-icon k-i-check"></span>Save changes</a>
<a role="button" id="cancelmeasureChanges" class="k-button k-button-icontext k-grid-cancel-changes" href="\\#"><span class="k-icon k-i-cancel"></span>Cancel changes</a>
<a role="button" id="ArchiveChanges" class="k-button" href="\\#" onClick="Archive()"><span class="k-icon"></span>Archive</a>
@*@(Html.Kendo().DropDownList()
.Name("InvoicedList")
.OptionLabel("All")
.DataTextField("InvoiceSatusName")
.DataValueField("InvoiceStatusId")
.AutoBind(true)
.Events(e => e.Change("invoicedStatusChange"))
.DataSource(ds =>
{
ds.Read("InvoiceStatuses", "EmPowerInvoiceReport");
})
.ToClientTemplate()
)*@
</div>
</script><script type="text/javascript">
function Archive() {
var items = {};
//var items = [];
var grid = $('#EmpFSRollGrid').data('kendoGrid');
var selectedElements = grid.select();
for (var j = 0; j < selectedElements.length; j++) {
var item = grid.dataItem(selectedElements[j]);
//items.push(item);
items['archiveItems[' + j + ']'] = item;
//items[j] = item;
}
$.ajax({
type: "POST",
data: items,
url: '@Url.Action("Archive", "EmPowerReconciliation")',
success: function (result) {
console.log(result);
}
})
}
// ******* Select/deSelect All
function selectAll(mainCheck) {
var grid = $("#EmpFSRollGrid").data("kendoGrid");
var items = grid.items();
items.each(function (index, td) {
var chckbx = $(td).find("input").get(0);
$(chckbx).prop("checked", mainCheck.checked);
var dataItem = grid.dataItem(this);
dataItem.IsSubmitted = mainCheck.checked;
if (mainCheck.checked) {
//$(chckbx).closest("td").addClass("k-dirty-cell").prepend("<span class='k-dirty'></span>");
$(chckbx).closest("tr").addClass("k-state-selected");
dataItem.dirty = true;
dataItem.dirtyFields = { IsSubmitted: true }
}
else {
//$(chckbx).closest("td").removeClass("k-dirty-cell").remove("span.k-dirty");
$(chckbx).closest("tr").removeClass("k-state-selected");
dataItem.dirty = false;
dataItem.dirtyFields = { IsSubmitted: false }
}
})
if (mainCheck.checked == false) {
dataSource = $("#EmpFSRollGrid").data("kendoGrid").dataSource
grid._selectedIds = {};
grid.clearSelection();
}
}
// ***************** Grid Textbox edited
$("#EmpFSRollGrid").on("change", "input.text-box.single-line.k-valid", function (e) {
var grid = $("#EmpFSRollGrid").data("kendoGrid"),
dataItem = grid.dataItem($(e.target).closest("tr"));
if (dataItem.dirty) {
grid.dataItem($(e.target).closest("tr").addClass("k-state-selected"));
var chk = $(e.target).closest("tr").find(".k-checkbox");
chk.prop("checked", true);
}
});
// *************** Grid checkbox checked/unchecked
$("#EmpFSRollGrid").on("change", "input.k-checkbox", function (e) {
var grid = $("#EmpFSRollGrid").data("kendoGrid"),
dataItem = grid.dataItem($(e.target).closest("tr"));
dataItem.IsSubmitted = this.checked;
if (this.checked) {
//$(e.target).closest("td").addClass("k-dirty-cell").prepend("<span class='k-dirty'></span>");
dataItem.dirty = true;
dataItem.dirtyFields = { IsSubmitted: true }
}
else {
// $(e.target).closest("td").removeClass("k-dirty-cell").remove("span.k-dirty");
dataItem.dirty = false;
dataItem.dirtyFields = { IsSubmitted: false }
var row = e.target.closest('tr')
var uid = $(row).data(uid)
dataSource = $("#EmpFSRollGrid").data("kendoGrid").dataSource
var item = dataSource.getByUid(uid.uid);
dataSource.cancelChanges(item);
grid.refresh();
}
if (!this.checked) {
$("#selectAll").prop('checked', false);
}
});
// ************** Clear the grid after an Update
function request_end(e) {
var grid = $("#EmpFSRollGrid").data("kendoGrid");
var items = grid.items();
items.each(function (index, td) {
var chckbx = $(td).find("input").get(0);
$(chckbx).prop("checked", false);
$(chckbx).closest("tr").removeClass("k-state-selected");
});
grid._selectedIds = {};
grid.clearSelection();
}
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
}
}
</script>
The important part is here.
<a role="button" id="ArchiveChanges" class="k-button" href="\\#" onClick="Archive()"><span class="k-icon"></span>Archive</a>
Here:
function Archive() {
var items = {};
//var items = [];
var grid = $('#EmpFSRollGrid').data('kendoGrid');
var selectedElements = grid.select();
for (var j = 0; j < selectedElements.length; j++) {
var item = grid.dataItem(selectedElements[j]);
//items.push(item);
items['archiveItems[' + j + ']'] = item;
//items[j] = item;
}
$.ajax({
type: "POST",
data: items,
url: '@Url.Action("Archive", "EmPowerReconciliation")',
success: function (result) {
console.log(result);
}
})
}
Controller
[AcceptVerbs("Post")]
public async Task<ActionResult> Archive([DataSourceRequest] DataSourceRequest request
,IEnumerable<EmPowerReconciliationDto> archiveItems)
{
return Json(archiveItems);
}