In our UI for ASP.NET Core R3 2020 (2020.3.915) release, the Column menu message of unsticking a column is "null".
This bug will be resolved in our next official release.
In the meantime, as a workaround, manually set the Unstick Column menu message:
.ColumnMenu(c => c.Messages(m => m.Unstick("Unstick Column")))I feel like this should be simple but I can't figure this out. I use the [Display(Name = "Code")] annotation in my view model. I have a simple custom editor popup on my grid. I use taghelpers because I just do. I am trying to get my labels to show the display name in my popup. I have seen older posts where validation is also not working but I think this has been fixed. Either way I feel like this should work.
Model
public class ChargeViewModel
{
[ScaffoldColumn(false)]
public int ChargesID { get; set; }
[Required]
[UIHint("EditChargePopup")]
[Display(Name = "Code")]
public string ChargesCodeID { get; set; }
Custom Editor
<div class="col-4">
<label for="ChargesCodeID" />
<kendo-textbox for="ChargesCodeID" />
</div>
<div class="col-4">
<label for="Charges_Name" />
<kendo-textbox for="Charges_Name" />
</div>
<div class="col-4">
<label for="Charges_Fee" />
<kendo-numerictextbox for="Charges_Fee" format="c2" decimals="2" />
</div>
Results

I have created a fresh project with the following variables:
I am trying to create a simple grid as following that has an editable `DateTime?` column:
https://netcorerepl.telerik.com/GpFmvpEr29UDYPJN54
It works in the REPL link above, but if I press "Edit" on my local project, the DateTime column defaults to a text input without the datetimepicker buttons (see Attachment-1.png), I'm not sure what I am missing.
I've checked that `/Views/Shared/Editor/Templates/DateTime.cshtml` exists and the content is as follows:
@model DateTime?
@(Html.Kendo().DateTimePickerFor(m => m).HtmlAttributes(new { title = Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName("")}))I've placed either `[DataType("Date")]` or `[DataType("DateTime")]` annotation on the class property definition and neither worked.
I've used `.EditorTemplateName("DateTime")` and/or `[UIHint("DateTime")]` and it didn't work.
I've created a new Template type and it didn't work.
I'm not sure what else to try to make it work.
I am converting a MVC table grid to a Telerik Grid. While looking at it, there are conditional columns. For example:
@if (Model?.GroupDetail?.IsMec == false)
{
<th class="text-secondary" style="width: 140px;">Group Info</th>
}
<th class="text-secondary">
@if (Model?.GroupDetail?.IsMec == false)
{
<text>Office</text>
}
else
{
<text>Role</text>
}
</th>I am trying to put an "action" menu on the toolbar of my grid. I have used a dropdownlist as is shown on your examples. The issue that I have with this is that action menus have a placeholder because all of the menu items have equal importance so no one menu item is the default. So I have rigged up menu like events with my javascript but it is still not ideal since the "placeholder" is a selectable list item. So then I had the brilliant idea of using telerik's menu within my custom client template. Easy peasy. Right? No, the dropdown or the .k-animation-container .k-animation-container-shown's z-order is 10002 and no matter how hard I try I can't get it to change and the dropdown is hidden by the grid header.
I was left to wonder if it is because it is limited to the confines of the toolbar. I am open to suggestions. I would hate to have to go back to the clunky dropdownlist option. Here's my code:
<style>I have a grid that only has a Delete button defined. The user can add a new record inline. How can I show the Save and Cancel buttons instead of the Delete button. They should not have an Edit button option.
Here is my code snippet:
@(
Html.Kendo().Grid<CommunityAssociationMasterModel>()
.Name("CommunityAssociationMasterList")
.Columns(columns =>
{
columns.Bound(p => p.DistrictCode).Title("District").Width(70);
columns.Bound(p => p.IndexNumber).Title("Index").Width(100);
columns.Bound(p => p.CreditName).Title("Credit");
columns.Command(command => { command.Destroy(); }).Width(210);
})
.ToolBar(toolbar => { toolbar.Create().Text("Add Credit Account"); toolbar.Excel(); })
.Sortable()
.Scrollable()
.Pageable()
.HtmlAttributes(new { style = "height:650px;" })
.Events(events => events.Change("onChange"))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Events(events => events.Error("error_handler"))
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.MasterCreditId);
model.Field(p => p.DistrictCode);
model.Field(p => p.IndexNumber);
model.Field(p => p.CreditName).DefaultValue("Community Assoc Credit").Editable(false);
})
.Read(read => read.Action("CommunityAssociation_Read", "CommunityAssociation"))
.Create(create => create.Action("CommunityAssociation_Create", "CommunityAssociation"))
.Destroy(read => read.Action("CommunityAssociation_Delete", "CommunityAssociation"))
)
I'm sure this is easy but I'm just not finding it.

Hi,
I need sample code for Asp.net core MVC Kendo Grid where Parent grid will be there & on any row click of parent grid, child grid will be load on same page.
Parent grid will be hide on that point when child grid will be displayed.
I also want to load a 'Subchild' grid on child grid row click in a popup.
I also want to save/load all grid's state data like column selected, filter, sorting & searching etc as well.
I can't find similar solution on forum. Please share if anyone have similar code example.
Thanks in advance.

// the template reference
.ClientDetailTemplateId("template-controls")
//the child grid definition, variable interpolation in the grid name and the toolbar, both work
<script id="template-controls" type="text/x-kendo-template">
@(Html.Kendo().Grid<ChildItem>()
.Name("GroupGrid_#=GroupID#")
.ToolBar(toolbar =>
{
toolbar.Template(
"<div class='edit-toolbar'>"
+"<button onclick='editChild(" + Model.ID + ",0,#=GroupID#, this)'>Edit</button>"
+ "</div>"
);
})
)
</script>
But when this code is migrated to ASP.NET Core using Tag Helpers, the variable interpolation in the toolbar does not occur. I would like to know whether this is an error in my code or a feature that is no longer supported.
//the template reference
<grid-detail-template>
<kendo-grid name="GroupGrid_${data.GroupID}">
<toolbar client-template-id="GroupGrid_Toolbar"></toolbar>
</kendo-grid>
</grid-detail-template>
//the child grid definition, variable interpolation works in the grid name , but the interpolation in toolbar do not
<script id="GroupGrid_Toolbar" type="text/html">
<div class='edit-toolbar'>
<button onclick=' editChild(@Model.ID,0,#=GroupID#, this)'>Edit</button>
</div>
</script>with (data) {
$kendoOutput = '\n\n <div class=\'edit-toolbar\'>\n <button onclick=\'editChild(11941,0,' + (GroupID) + ', this)\' \n >\n ' + ($kendoHtmlEncode(data.GroupID)) + ' : ' + (GroupID) + ' Edit #\n </button>\n </div>\n ';
}<toolbar>
<toolbar-button>
<toolbar-command-template>
// the variable interpolation placed here
</toolbar-command-template>
</toolbar-button>
</toolbar> I have a .net core 8 web application, that has a grid that loads data via Ajax. When I edit a row, I'd like the `Contract` column to be a multi-select dropdown. When I edit a row, the control is rendered, but there is no data in it. I have set static data and the data does show up.
Here's my grid:
@(
Html.Kendo().Grid<ContractBenefitViewModel>()
.Name("ContractBenefitGrid")
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden(true);
columns.Bound(c => c.Contracts)
.ClientTemplate("#= displayContracts(data) #")
.EditorTemplateName("Contracts")
.Width(400)
.Filterable(false)
.Sortable(false);
columns.ForeignKey(c => c.BenefitId, (IEnumerable)ViewBag.Benefits, "Id", "DisplayName");
columns.Bound(c => c.Gl)
.Width(150);
columns.Bound(c => c.Comments);
columns.Bound(c => c.Active).Hidden(true);
columns.Bound(c => c.Deleted).Hidden(true);
columns.Command(command =>
{
command.Edit();
command.Destroy();
})
.HtmlAttributes(new { style = "text-align: center;" })
.Width(200);
})
.Editable(editable => editable.Mode(GridEditMode.InLine))
.ToolBar(toolbar =>
{
toolbar.Create();
})
.Pageable(pager =>
{
pager.Refresh(true);
pager.PageSizes([10, 20, 50]);
})
.Sortable()
.Filterable()
.NoRecords()
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.PageSize(10)
.ServerOperation(true)
.Events(events => events.Error("error_handler").RequestEnd("onRequestEnd('staticNotifications')"))
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Contracts).DefaultValue(ViewBag.ContractId as List<ContractModel> ?? new List<ContractModel>());
model.Field(p => p.BenefitValue).DefaultValue(ViewBag.BenefitId);
model.Field(p => p.Comments);
model.Field(p => p.LastUpdatedBy).DefaultValue(ViewData[Literals.EmailKey]);
model.Field(p => p.Active).Editable(false).DefaultValue(Literals.Yes);
model.Field(p => p.Deleted).Editable(false).DefaultValue(Literals.No);
})
.Filter(f =>
{
f.Add(x => x.Active).IsEqualTo(Literals.Yes);
f.Add(x => x.Deleted).IsEqualTo(Literals.No);
})
.Read(read => read.Action("GetContractBenefits", "ContractBenefit").Data("forgeryToken"))
.Create(create => create.Action("CreateContractBenefits", "ContractBenefit").Data("forgeryToken"))
.Update(update => update.Action("UpdateContractBenefits", "ContractBenefit").Data("forgeryToken"))
.Destroy(destroy => destroy.Action("DeleteContractBenefits", "ContractBenefit").Data("forgeryToken"))
.Sort(sort =>
{
sort.Add(x => x.BenefitValue);
})
)
)Here's the JavaScript
<script type="text/javascript">
function displayContracts(data) {
window.console.log('displayContracts()');
return $.map(data.Contracts, function (e) { return e.DisplayName; }).join(", ");
}
</script>Here's my model
public class ContractBenefitViewModel
{
public long Id { get; set; }
public long BenefitId { get; set; }
[Display(Name = "Benefit")]
public string BenefitValue
{
get
{
var sb = new StringBuilder();
if (Benefit is not null)
{
sb.Append(Benefit.Value);
if (!string.IsNullOrWhiteSpace(Benefit.Gl))
{
sb.Append(" (");
sb.Append(Benefit.Gl);
sb.Append(")");
}
}
return sb.ToString();
}
}
[Display(Name = "GL Code")]
public string Gl => Benefit?.Gl ?? string.Empty;
[Display(Name = "Comments")]
[StringLength(ModelLiterals.CommentsLength)]
[MaxLength(ModelLiterals.CommentsLength)]
public string? Comments { get; set; }
public string Active { get; set; } = ModelLiterals.Yes;
public string Deleted { get; set; } = ModelLiterals.No;
public string LastUpdatedBy { get; set; } = string.Empty;
public BenefitModel? Benefit { get; set; } = null!;
[UIHint("Contracts")]
public IList<ContractModel> Contracts { get; set; } = new List<ContractModel>();
}Here's my Editor Template (named Contracts.cshtml, in the EditorTemplates folder)
@model Lookups.ContractModel
<div style="width: 99%">
@(Html.Kendo().MultiSelectFor(m => m)
.DataValueField("Id")
.DataTextField("DisplayName")
.DownArrow()
.AutoClose(false)
.BindTo((IEnumerable<Lookups.ContractModel>)ViewData["contracts"])
)
</div>Here's the Index and Get data methods in my controller
[HttpGet]
public async Task<IActionResult> IndexAsync()
{
Logger.LogDebug("{NameOf}()", nameof(IndexAsync));
var contracts = await Client.GetContractsAsync(); //Client is my API client library - it fetches data from my API
var benefits = await Client.GetBenefitsAsync();
ViewBag.Contracts = contracts;
ViewData["contracts"] = contracts;
ViewBag.Benefits = benefitFinancialSupports;
ViewBag.DefaultContractId = contracts?.FirstOrDefault()?.Id ?? -1;
ViewBag.DefaultBenefitId = benefits?.FirstOrDefault()?.Id ?? -1;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> GetContractBenefitsAsync([DataSourceRequest] DataSourceRequest request)
{
Logger.LogDebug("{NameOf}()", nameof(GetContractBenefitsAsync));
var stopwatch = Stopwatch.StartNew();
try
{
if (!ModelState.IsValid) return Json(InvalidModelStateMessage);
var models = await Client.GetContractBenefitsAsync();
var viewModels = models
.Where(x => x is { Benefit: not null, Contract: not null })
.GroupBy(x => x.BenefitId)
.Select(g => new ContractBenefitViewModel
{
BenefitId = g.Key,
Benefit = g.First().Benefit,
Contracts = g.Select(x => x.Contract!).Distinct().ToList(),
Id = g.First().Id,
Comments = g.First().Comments,
Active = g.First().Active,
Deleted = g.First().Deleted,
LastUpdatedBy = g.First().LastUpdatedBy
})
.ToList();
return Json(await viewModels.ToDataSourceResultAsync(request));
}
catch (Exception ex)
{
Logger.LogError(ex, "{NameOf}()", nameof(GetContractBenefitsAsync));
return Json(new { success = false, message = ex.Message });
}
finally
{
stopwatch.Stop();
Logger.LogInformation("**** {NameOf} took [{Elapsed}]", nameof(GetContractBenefitsAsync),
stopwatch.Elapsed);
}
}
I should mention that I store the data one ContractId with one BenefitId (in a Mapping table), so when I return data via the `Client.GetContractBenefitsAsync()` call, it returns a List of 1-to-1 records, and I group them so I get a single Benefit with all Contracts that are associated with it (hence the Linq GroupBy call to build my ViewModel). This is how I want to present it to my users, so they can select as many Contracts as they want in the UI, and behind the scenes I'll turn into a 1:1 association. I'm just having trouble getting my data (the Contracts Multi Select) to display data. Am I missing something or is there another way to do this?
