Howdy.. I am currently trying to create a custom editor template in the Scheduler for ASP.NET CORE using Razor pages. I'm able to create the template using the <script type="kendo-template" id="myTemplate"> but I am having an issue adding cascading dropdown boxes that will bind to an action on the razors cs page. Is this possible and if so what is the preferred method to achive this.
Thanks.....
1 Answer, 1 is accepted
Hi randy2101,
When using HTML wrappers you can create a EditorTemplate, place it in the ~/Pages/Shared/EditorTemplates folder and then point the Scheduler that a particular template should be used for editing the events.
That said you can create cascading DropDownLists in a custom template the following way:
Define a Scheduler and set the custom template for editing:
@(Html.Kendo().Scheduler<TelerikAspNetCoreApp346.Data.MeetingViewModel>()
.Name("scheduler")
.Height(600)
.Views(views =>
{
views.DayView();
views.WeekView(weekView => weekView.Selected(true));
views.MonthView();
views.AgendaView();
})
.Editable(e=>e.TemplateName("~/Pages/Shared/EditorTemplates/CustomEditor.cshtml"))
.Timezone("Etc/UTC")
.Resources(resource =>
{
resource.Add(m => m.RoomID)
.Title("Room")
.DataTextField("Text")
.DataValueField("Value")
.DataColorField("Color")
.BindTo(new[] {
new { Text = "Meeting Room 101", Value = 1, Color = "#6eb3fa" },
new { Text = "Meeting Room 201", Value = 2, Color = "#f58a8a" }
});
resource.Add(m => m.Attendees)
.Title("Attendees")
.Multiple(true)
.DataTextField("Text")
.DataValueField("Value")
.DataColorField("Color")
.BindTo(new[] {
new { Text = "Alex", Value = 1, Color = "#f8a398" },
new { Text = "Bob", Value = 2, Color = "#51a0ed" },
new { Text = "Charlie", Value = 3, Color = "#56ca85" }
});
})
.DataSource(d => d
.Model(m =>
{
m.Id(f => f.MeetingID);
m.Field(f => f.Title).DefaultValue("No title");
m.Field(f => f.Attendees).DefaultValue(1);
m.RecurrenceId(f => f.RecurrenceID);
})
.Events(e => e.Error("error_handler"))
.Read(read=>read.Url(Url.Page("Index","Meetings_Read")).Data("forgeryToken"))
.Create(create=>create.Url(Url.Page("Index", "Meetings_Create")).Data("forgeryToken"))
.Destroy(destroy=>destroy.Url(Url.Page("Index", "Meetings_Destroy")).Data("forgeryToken"))
.Update(u=>u.Url(Url.Page("Index", "Meetings_Update")).Data("forgeryToken"))
)
)
<script>
function forgeryToken() {
return kendo.antiForgeryTokens();
}
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);
var scheduler = $("#scheduler").data("kendoScheduler");
scheduler.one("dataBinding", function (e) {
//prevent saving if server error is thrown
e.preventDefault();
})
}
}
function filterProducts() {
return {
categoryId: $("#CategoryID").val(),
__RequestVerificationtoken:forgeryToken().__RequestVerificationtoken
};
}
</script>
CustomEditor.cshtml
@model TelerikAspNetCoreApp346.Data.MeetingViewModel
@{
//required in order to render validation attributes
ViewContext.FormContext = new FormContext();
}
@functions{
public Dictionary<string, object> generateDatePickerAttributes(
string elementId,
string fieldName,
string dataBindAttribute,
Dictionary<string, object> additionalAttributes = null)
{
Dictionary<string, object> datePickerAttributes = additionalAttributes != null ? new Dictionary<string, object>(additionalAttributes) : new Dictionary<string, object>();
datePickerAttributes["id"] = elementId;
datePickerAttributes["name"] = fieldName;
datePickerAttributes["data-bind"] = dataBindAttribute;
datePickerAttributes["required"] = "required";
datePickerAttributes["style"] = "z-index: inherit;";
return datePickerAttributes;
}
}
<div class="k-edit-label">
@(Html.LabelFor(model => model.Title))
</div>
<div data-container-for="title" class="k-edit-field">
@(Html.TextBoxFor(model => model.Title, new { @class = "k-textbox", data_bind = "value:title" }))
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.Start))
</div>
<div data-container-for="start" class="k-edit-field">
@(Html.Kendo().DateTimePickerFor(model => model.Start)
.HtmlAttributes(generateDatePickerAttributes("startDateTime", "start", "value:start,invisible:isAllDay")))
@(Html.Kendo().DatePickerFor(model => model.Start)
.HtmlAttributes(generateDatePickerAttributes("startDate", "start", "value:start,visible:isAllDay")))
<span data-bind="text: startTimezone"></span>
<span data-for="start" class="k-invalid-msg"></span>
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.End))
</div>
<div data-container-for="end" class="k-edit-field">
@(Html.Kendo().DateTimePickerFor(model => model.End)
.HtmlAttributes(generateDatePickerAttributes(
"endDateTime",
"end",
"value:end,invisible:isAllDay",
new Dictionary<string, object>() {{"data-dateCompare-msg", "End date should be greater than or equal to the start date"}})))
@(Html.Kendo().DatePickerFor(model => model.End)
.HtmlAttributes(generateDatePickerAttributes(
"endDate",
"end",
"value:end,visible:isAllDay",
new Dictionary<string, object>() {{"data-dateCompare-msg", "End date should be greater than or equal to the start date"}})))
<span data-bind="text: endTimezone"></span>
<span data-for="end" class="k-invalid-msg"></span>
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.IsAllDay))
</div>
<div data-container-for="isAllDay" class="k-edit-field">
<input data-bind="checked: isAllDay" data-val="true" id="IsAllDay" name="IsAllDay" type="checkbox" />
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.RecurrenceRule))
</div>
<div data-container-for="recurrenceRule" class="k-edit-field">
@(Html.Kendo().RecurrenceEditorFor(model => model.RecurrenceRule)
.HtmlAttributes(new { data_bind = "value:recurrenceRule" }))
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.Description))
</div>
<div data-container-for="description" class="k-edit-field">
@(Html.TextAreaFor(model => model.Description, new { @class = "k-textbox", data_bind = "value:description" }))
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.RoomID))
</div>
<div data-container-for="RoomID" class="k-edit-field">
@(Html.Kendo().DropDownListFor(model => model.RoomID)
.HtmlAttributes(new { data_bind = "value:RoomID", style = "width: 200px" })
.DataTextField("Text")
.DataValueField("Value")
.OptionLabel("None")
.ValuePrimitive(true)
.Template("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
.BindTo(new[] {
new { Text = "Meeting Room 101", Value = 1, Color = "\\#6eb3fa" },
new { Text = "Meeting Room 201", Value = 2, Color = "\\#f58a8a" }
}).ToClientTemplate()
)
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.Attendees))
</div>
<div data-container-for="Attendees" class="k-edit-field">
@(Html.Kendo().MultiSelectFor(model => model.Attendees)
.HtmlAttributes(new { data_bind = "value:Attendees" })
.DataTextField("Text")
.DataValueField("Value")
.ValuePrimitive(true)
.TagTemplate("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
.ItemTemplate("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
.BindTo(new[] {
new { Text = "Alex", Value = 1, Color = "\\#f8a398" },
new { Text = "Bob", Value = 2, Color = "\\#51a0ed" },
new { Text = "Charlie", Value = 3, Color = "\\#56ca85" }
})
)
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.CategoryID))
</div>
<div data-container-for="Attendees" class="k-edit-field">
@(Html.Kendo().DropDownListFor(x=>x.CategoryID)
.HtmlAttributes(new { data_bind = "value:CategoryID" })
.OptionLabel("Select category...")
.DataTextField("CategoryName")
.DataValueField("CategoryID")
.ValuePrimitive(true)
.DataSource(source =>
{
source.Read(read =>
{
read.Url(Url.Page("Index","Categories")).Data("forgeryToken");
});
})
)
</div>
<div class="k-edit-label">
@(Html.LabelFor(model => model.ProductID))
</div>
<div data-container-for="Attendees" class="k-edit-field">
@(Html.Kendo().DropDownListFor(x=>x.ProductID)
.HtmlAttributes(new { data_bind = "value:ProductID" })
.OptionLabel("Select product...")
.DataTextField("ProductName")
.DataValueField("ProductID")
.ValuePrimitive(true)
.DataSource(source =>
{
source.Read(read =>
{
read.Url(Url.Page("Index", "Products"))
.Data("filterProducts");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("CategoryID")
)
</div>
As a result you will have two cascading DropDownLists in the editor template. Here is a screencast demonstrating the above.
I hope this helps.
Regards,
Aleksandar
Progress Telerik
Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.