@(
Html.Kendo().Grid<IndexModel.CompanyFinancialVM>()
.Name("gridCompanyFinancial")
.Navigatable()
.Height(590)
.Sortable()
.Editable(e => e.Mode(GridEditMode.InCell))
.Scrollable()
.ToolBar(t => { t.Save(); t.CancelEdit(); })
.Columns(columns =>
{
columns.Bound(f => f.CompanyName).Title("Company").Width(150);
columns.Bound(f => f.PeriodName).Title("Period").Width(120);
columns.Bound(f => f.VariableName).Title("Variable").Width(150);
columns.Bound(f => f.VariableTypeName).Title("Variable Type").Width(120);
columns.Bound(f => f.Val).Title("Val")
.Width(100)
.Format("{0:n}") // Show 4 decimals and thousand separator
.EditorTemplateName("Decimal");
columns.Bound(f => f.ValCurr)
.Title("Currency")
.ClientTemplate("#= getCurrencyName(ValCurr) #")
.EditorTemplateName("Currency")
.Width(120);
columns.Bound(f => f.QuantumFK)
.Title("Quantum")
.ClientTemplate("#= getQuantumName(QuantumFK) #")
.EditorTemplateName("QuantumFK")
.Width(120);
columns.Bound(f => f.Priority).Title("Priority").Width(80);
columns.Bound(f => f.SpecOrder).Title("Spec Order").Width(100);
columns.Bound(f => f.Rem).Title("Remarks").EditorTemplateName("Rem");
})
.DataSource(ds => ds.Ajax()
.Read(r => r.Url(Url.Content("~/CompanyFinancial/Index?handler=Read")).Data("getGridRequestData"))
.Update(u => u.Url(Url.Content("~/CompanyFinancial/Index?handler=Update")).Data("forgeryToken"))
.Batch(true)
.Model(m =>
{
m.Id(f => f.Nr);
m.Field(f => f.CompanyName);
m.Field(f => f.PeriodName);
m.Field(f => f.VariableName);
m.Field(f => f.VariableTypeName);
m.Field(f => f.Priority);
m.Field(f => f.SpecOrder);
m.Field(f => f.Val);
m.Field(f => f.ValCurr);
m.Field(f => f.QuantumFK);
m.Field(f => f.Rem);
})
.Sort(s => s.Add(f => f.SpecOrder).Ascending())
.PageSize(20)
)
.Pageable()
//Add a dropdown tool for inserting symbols.
string selectTitle = "Select a symbol to insert";
//Standard html select.
//Cannot find a way to use an html Select in Kendo 2025Q1. This worked in Kendo 2024.Q4,
// after removing the 'ref-toolbar-tool' attribute from the div preceding the Select.
string toolNameSelect = $"insertSymbol-{EditorIdClean}";
string dropdownNameSelect = $"symbolSelect_{EditorIdClean}";
string symbolSelect = $"<label for='{dropdownNameSelect}' class='visually-hidden'>Symbol:</label>" +
$"<select id='{dropdownNameSelect}' " +
$"title='{selectTitle}' " +
$"aria-label='{selectTitle}' " +
"style='width:150px' " +
"onclick='testSymbolSelect(this)' " + //The click event is registered * the alert appears.
"onchange='InsertSymbolSelect(this)' " +
">" +
$"{symbolHtmlSelectOptions()}" +
$"</select>";
toolFactories.Add(tools => tools
.CustomTemplate(x => x
.Name(toolNameSelect)
.Tooltip(selectTitle)
.Template(symbolSelect)
));
When clicking the Add new record button on a grid from the Toolbar.Create method I am getting an error: kendo.all.js:3314 Uncaught TypeError: Cannot read properties of undefined (reading 'IsActive'). I'm using a ViewModel that is as follows:
public class PersonAddressViewModel
{
public List<PersonInfo>? PersonInfoList { get; set; }
public List<PersonAddress>? PersonAddressList { get; set; }
public PersonInfo? Person { get; set; }
public PersonAddress? Address { get; set; }
}
which is referencing these:
public partial class PersonInfo
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(120)]
[Unicode(false)]
public string Name { get; set; }
public int Age { get; set; }
[Required]
[StringLength(10)]
[Unicode(false)]
public string Sex { get; set; }
[Required]
[StringLength(120)]
[Unicode(false)]
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
[StringLength(120)]
[Unicode(false)]
public string? UpdatedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public bool IsActive { get; set; }
[InverseProperty("FkPersonInfoNavigation")]
public virtual ICollection<PersonAddress>? PersonAddresses { get; set; } = new List<PersonAddress>();
}
public partial class PersonAddress
{
[Key]
public int Id { get; set; }
[StringLength(120)]
[Unicode(false)]
public string StreetAddress { get; set; }
[StringLength(120)]
[Unicode(false)]
public string City { get; set; }
[StringLength(2)]
[Unicode(false)]
public string State { get; set; }
[StringLength(10)]
[Unicode(false)]
public string Zip { get; set; }
[Column("FK_PersonInfo")]
public int FkPersonInfo { get; set; }
[ForeignKey("FkPersonInfo")]
[InverseProperty("PersonAddresses")]
public virtual PersonInfo FkPersonInfoNavigation { get; set; }
}
This is my cshtml:
@(
Html.Kendo().DataSource<PersonAddressViewModel>()
.Name("DsPerAddVM")
.Ajax(datasource => datasource
.ServerOperation(false)
.Model(model =>
{
model.Id(perAdd => perAdd.Person.Id);
model.Field(perAdd => perAdd.Person.Id).Editable(false);
model.Field(perAdd => perAdd.Person.IsActive).DefaultValue(true);
model.Field(perAdd => perAdd.Person.Name).DefaultValue("Enter Name");
model.Field(perAdd => perAdd.Person.Age).DefaultValue(0);
model.Field(perAdd => perAdd.Person.Sex).DefaultValue("Optional");
model.Field(perAdd => perAdd.Person.CreatedBy).Editable(false).DefaultValue("Some User");
model.Field(perAdd => perAdd.Person.CreatedDate).Editable(false).DefaultValue(DateTime.Now);
model.Field(perAdd => perAdd.Person.UpdatedBy).Editable(false);
model.Field(perAdd => perAdd.Person.UpdatedDate).Editable(false);
model.Field(perAdd => perAdd.Address.Id).Editable(false);
model.Field(p => p.Address.FkPersonInfo).Editable(false);
})
.Read(read => read.Action("KendoRead", "Home"))
.Create(create => create.Action("KendoCreate", "Home"))
.Update(update => update.Action("KendoUpdate", "Home"))
.Destroy(destroy => destroy.Action("KendoDelete", "Home"))
)
)
<div>
@(
Html.Kendo().Grid<PersonAddressViewModel>()
.Name("UserGrid")
.Columns(columns =>
{
columns.Bound(perAdd => perAdd.Person.IsActive);
columns.Bound(perAdd => perAdd.Person.Name);
columns.Bound(perAdd => perAdd.Person.Age);
columns.Bound(perAdd => perAdd.Person.Sex);
columns.Bound(perAdd => perAdd.Address.StreetAddress);
columns.Bound(perAdd => perAdd.Address.City);
columns.Bound(perAdd => perAdd.Address.State);
columns.Bound(perAdd => perAdd.Address.Zip);
columns.Command(command => command.Destroy());
})
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
toolbar.Search();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Scrollable()
.DataSource("DsPerAddVM")
)
</div>
My grid loads the data as expected with the following methods (image attached):
public ActionResult KendoRead([DataSourceRequest] DataSourceRequest dsRequest)
{
List<PersonAddressViewModel> perAddList = KendoViewServices.GetGridData(_context);
return Json(perAddList.ToDataSourceResult(dsRequest));
}
public static List<PersonAddressViewModel> GetGridData(TestJohnCrudOpContext context)
{
context = context;
List<PersonAddressViewModel> perAddList = [];
PersonAddressViewModel GetPerAddVm = new()
{
PersonInfoList = [],
PersonAddressList = []
};
GetPerAddVm.PersonInfoList = context.PersonInfo.ToList();
GetPerAddVm.PersonAddressList = context.PersonAddresses.ToList();
foreach (PersonInfo person in GetPerAddVm.PersonInfoList)
{
PersonAddressViewModel perAddVm = new()
{
Person = new PersonInfo
{
Id = person.Id,
Name = person.Name,
Age = person.Age,
Sex = person.Sex,
CreatedBy = person.CreatedBy,
CreatedDate = person.CreatedDate,
UpdatedBy = person.UpdatedBy,
UpdatedDate = person.UpdatedDate,
IsActive = person.IsActive
}
};
foreach (PersonAddress address in GetPerAddVm.PersonAddressList.Where(w => w.FkPersonInfo == person.Id))
{
perAddVm.Address = new PersonAddress
{
Id = address.Id,
StreetAddress = address.StreetAddress,
City = address.City,
State = address.State,
Zip = address.Zip,
FkPersonInfo = address.FkPersonInfo
};
}
perAddList.Add(perAddVm);
}
perAddList.ToList();
return perAddList;
I've used this ViewModel to load and edit a standard HTML table with no issues. Also, updating the grid or performing a deletion works without error. I can tell that it is cutting off the first property of each field prior to the "." but I can't find a solution to correct this.
.ToolBar(toolbar =>{
toolbar .ClientTemplate(
"<text>" +
"<a class=\"k-primary" href=\””+@Url.Action ("CreateId", "Home") + "\">" "Create New Person" +
"</a>" +
"</text>");
toolbar .Excel().Text("Excel");
})
Excel(excel => excel
FileName("Tabledata.xlsx")
Filterable(true))
I am trying to add excel buuton the existing client template but, the excel is not coming only the create new preson button is only coming. If i write the excel individually then it is working. I want the create new person button next to it the excel button.
can some one plz look into this.
Thanks.
Events(e=>e.ExcelExport("excelExportHelper"). DataBound("datagridrows")) |
with this line the excel button is working but after upgrading the button is not showing. Can someone plz help with the issue
Thanks
Hello!
I am trying to add a <kendo-upload> tag onto the toolbar of a kendo grid using TagHelper and ASP.NET Core
Though I am struggling with figuring out how to do this, I have followed this template: https://demos.telerik.com/aspnet-core/grid/toolbar-template to not much success.
My goal is to simply add a file upload option to upload an excel file to populate the fields of a grid!
Any ideas on how to progress?
Thank you!
But I am still struggling
I have a grid with a Create button and Search field in the toolbar. I would like to add a count of the number of items in the grid. I am aware that it's possible to add paging to display the count and then disable it with:
PreviousNext(false).Numeric(false)
However, that results in wasted space because there's a row for the pager and count, and another row with the Create button and Search field.
Is it possible to add the item count to the custom toolbar so that everything is in in one row?
Thanks
Hello,
I want to add and clear menuButtons with javascript on the client but there is no Api for that. To add items with append like this shows the items but on click nothing happens (no close and no Event)
$(
"#Berichte_optionlist"
).append(
"<li><a href='' tabindex='0' title='test' class='k-button k-button-icontext' id="
test" data-overflow=
'auto'
>test</a></li>
How to add menuButtons the Right way so that the click Event works?
robert
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);
}