In fact, i try to adapt the code in this post http://www.telerik.com/forums/schedler-custom-editor-extra-field
The version used in this example is Kendo.Mvc 2013.3.1119.340 and the one i use is 2013.3.1511.440.
I'll try to explain it clear with sample of code.
-----------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------
:
public virtual JsonResult Meetings_Create([DataSourceRequest] DataSourceRequest request, MeetingViewModel meeting)
{
if (ModelState.IsValid)
{
meetingService.Insert(meeting, ModelState);
}
return Json(new[] { meeting }.ToDataSourceResult(request, ModelState));
}
My code 2013.3.1511.440 :
public virtual JsonResult TasksCreate([Kendo.Mvc.UI.DataSourceRequest]Kendo.Mvc.UI.DataSourceRequest request, TaskViewModel task)
{
if (ModelState.IsValid)
{
}
return null;
}
In this part the task recieved into the controller haven't the correct date of day : {01/01/0001 00:00:00}.
In the sample all is right.
-----------------------------------------------------------------------------
MODEL
-----------------------------------------------------------------------------
Sample 2013.3.1119.340 :
public class MeetingViewModel : ISchedulerEvent
{
public int MeetingID { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
private DateTime start;
[Required]
public DateTime Start
{
get
{
return start;
}
set
{
start = value.ToUniversalTime();
}
}
public string StartTimezone { get; set; }
private DateTime end;
[Required]
[DateGreaterThan(OtherField = "Start")]
public DateTime End
{
get
{
return end;
}
set
{
end = value.ToUniversalTime();
}
}
public string EndTimezone { get; set; }
public string RecurrenceRule { get; set; }
public int? RecurrenceID { get; set; }
public string RecurrenceException { get; set; }
public bool IsAllDay { get; set; }
public string Timezone { get; set; }
public int? RoomID { get; set; }
public IEnumerable<
int
> Attendees { get; set; }
My code 2013.3.1511.440 :
public class TaskViewModel : Kendo.Mvc.UI.ISchedulerEvent
{
//public int ID { get; set; }
public int TaskID { get; set; }
public int? OwnerID { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
private DateTime start;
[Required]
public DateTime Start
{
get
{
return start;
}
set
{
start = value.ToUniversalTime();
}
}
public string StartTimezone { get; set; }
private DateTime end;
[Required]
[DateGreaterThan(OtherField = "Start")]
public DateTime End
{
get
{
return end;
}
set
{
end = value.ToUniversalTime();
}
}
public string EndTimezone { get; set; }
public string RecurrenceRule { get; set; }
public int? RecurrenceID { get; set; }
public string RecurrenceException { get; set; }
public bool IsAllDay { get; set; }
public int? RoomID { get; set; }
public int Priority { get; set; }
public string Url { get; set; }
public int idOrganizator { get; set; }
public IEnumerable<
int
> DepartmentsID { get; set; }
}
-------------------------------------------------------------------------------
INDEX.cshtml
-------------------------------------------------------------------------------
Sample 2013.3.1119.340 :
@(Html.Kendo().Scheduler<
SchedulerCustomEditor.Models.MeetingViewModel
>()
.Name("scheduler")
.Date(new DateTime(2013, 6, 13))
.StartTime(new DateTime(2013, 6, 13, 7, 00, 00))
.Height(600)
.Views(views => {
views.DayView();
views.WeekView(weekView => weekView.Selected(true));
views.MonthView();
views.AgendaView();
})
.Editable(editable => {
editable.TemplateName("CustomEditorTemplate");
})
.Timezone("Etc/UTC")
.DataSource(d => d
.Model(m => {
m.Id(f => f.MeetingID);
m.Field(f => f.Title).DefaultValue("No title");
m.RecurrenceId(f => f.RecurrenceID);
})
.Events(e => e.Error("error_handler"))
.Read("Meetings_Read", "Home")
.Create("Meetings_Create", "Home")
.Destroy("Meetings_Destroy", "Home")
.Update("Meetings_Update", "Home")
)
)
<
script
type
=
"text/javascript"
>
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();
})
}
}
</
script
>
My code 2013.3.1511.440 :
@using iMail.Web.App_Code.Helpers
@using iMail.Web.Resources.Views.Calendar
<
div
class
=
"span9"
id
=
"CalendarSchelduler"
>
@(Html.Kendo().Scheduler<
iMail.Web.Models.TaskViewModel
>()
.Name("scheduler")
.Date(DateTime.Now)
.StartTime(new DateTime(2013, 6, 13, 7, 00, 00))
.Height(600)
.Views(views =>
{
views.DayView();
views.WeekView();
views.MonthView();
views.AgendaView(agenda => agenda.Selected(true));
})
.Selectable(true)
.Timezone("Etc/UTC")
.Events(e => e.Edit("onEdit"))
.Editable(editable => {
editable.TemplateName("_EditorTemplatePartial");
//editable.Resize(true);
})
.DataSource(d => d
.Model(m => {
m.Id(f => f.TaskID);
m.Field(f => f.Title).DefaultValue("No title");
m.RecurrenceId(f => f.RecurrenceID);
//m.Field(e => e.Attendees).DefaultValue(new List<
iMail.Web.Models.CalendarAttendeeModel
>());
})
.Events(e => e.Error("error_handler"))
.Read("TasksRead", "Calendar")
.Create("TasksCreate", "Calendar")
.Destroy("TasksDestroy", "Calendar")
.Update("TasksUpdate", "Calendar")
)
)
</
div
>
<
script
type
=
"text/x-kendo-template"
id
=
"schedulerTemplate"
>
<
div
id
=
"recurrenceEditor"
name
=
"recurrenceRule"
data-bind
=
"value: recurrenceRule"
/>
<
script
>
var options = jQuery("\#CalendarSchelduler").data("kendoScheduler").options;
jQuery("\#recurrenceEditor").kendoRecurrenceEditor({
start: "#=data.start#",
timezone: options.timezone,
messages: options.messages
});
<\/script>
</
script
>
<
script
type
=
"text/javascript"
>
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 onEdit(e) {
$(e.container).parent().css({
style: '.k-edit-form-container { width: auto;}'
});
alert("edit");
}
$(document).ready(function ()
{
});
</
script
>
---------------------------------------------------------------------------------------
THE TEMPLATE
---------------------------------------------------------------------------------------
Sample 2013.3.1119.340 :
@model SchedulerCustomEditor.Models.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"
>
@(Html.CheckBoxFor(model => model.IsAllDay, new { data_bind = "checked:isAllDay" }))
</
div
>
<
div
class
=
"endTimezoneRow"
>
<
div
class
=
"k-edit-label"
></
div
>
<
div
class
=
"k-edit-field"
>
<
label
class
=
"k-check"
>
<
input
checked
=
"checked"
class
=
"k-timezone-toggle"
type
=
"checkbox"
value
=
"true"
/>
Use separate start and end time zones
</
label
>
</
div
>
</
div
>
<
script
>
$(".k-timezone-toggle").on("click", function () {
var isVisible = $(this).is(":checked");
var container = $(this).closest(".k-popup-edit-form");
var endTimezoneRow = container.find("label[for='EndTimezone']").parent().add(container.find("div[data-container-for='endTimezone']"));
endTimezoneRow.toggle(isVisible);
if (!isVisible) {
var uid = container.attr("data-uid");
var scheduler = $("\#scheduler").data("kendoScheduler");
var model = scheduler.dataSource.getByUid(uid);
model.set("endTimezone", null);
}
});
var endTimezone = '${data.endTimezone}';
if (!endTimezone || endTimezone == "null") {
$(".k-timezone-toggle").trigger('click');
}
</
script
>
<
div
class
=
"k-edit-label"
>
@(Html.LabelFor(model => model.StartTimezone))
</
div
>
<
div
data-container-for
=
"startTimezone"
class
=
"k-edit-field"
>
@(Html.Kendo().TimezoneEditorFor(model => model.StartTimezone)
.HtmlAttributes(new { data_bind = "value:startTimezone" }))
</
div
>
<
div
class
=
"k-edit-label"
>
@(Html.LabelFor(model => model.EndTimezone))
</
div
>
<
div
data-container-for
=
"endTimezone"
class
=
"k-edit-field"
>
@(Html.Kendo().TimezoneEditorFor(model => model.EndTimezone)
.HtmlAttributes(new { data_bind = "value:endTimezone" }))
</
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
>
@{
ViewContext.FormContext = null;
}
My code 2013.3.1511.440 :
@model iMail.Web.Models.TaskViewModel
@using iMail.Web.App_Code.Helpers
@using iMail.Web.Resources.Views.Calendar
@{
//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"
>
@Index.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"
>
@Index.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"
>
@Index.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"
>
@Index.IsAllDay
</
div
>
<
div
data-container-for
=
"isAllDay"
class
=
"k-edit-field"
>
@(Html.CheckBoxFor(model => model.IsAllDay, new { data_bind = "checked:isAllDay" }))
</
div
>
<
div
class
=
"endTimezoneRow"
>
<
div
class
=
"k-edit-label"
></
div
>
<
div
class
=
"k-edit-field"
>
<
label
class
=
"k-check"
>
<
input
checked
=
"checked"
class
=
"k-timezone-toggle"
type
=
"checkbox"
value
=
"true"
/>
@Index.SeparateStartEndTimezone
</
label
>
</
div
>
</
div
>
<
script
>
$(".k-timezone-toggle").on("click", function () {
var isVisible = $(this).is(":checked");
var container = $(this).closest(".k-popup-edit-form");
var endTimezoneRow = container.find("label[for='EndTimezone']").parent().add(container.find("div[data-container-for='endTimezone']"));
endTimezoneRow.toggle(isVisible);
if (!isVisible) {
var uid = container.attr("data-uid");
var scheduler = $("\#scheduler").data("kendoScheduler");
var model = scheduler.dataSource.getByUid(uid);
model.set("endTimezone", null);
}
});
var endTimezone = '${data.endTimezone}';
if (!endTimezone || endTimezone == "null") {
$(".k-timezone-toggle").trigger('click');
}
</
script
>
<
div
class
=
"k-edit-label"
>
@Index.StartTimezone
</
div
>
<
div
data-container-for
=
"startTimezone"
class
=
"k-edit-field"
>
@(Html.Kendo().TimezoneEditorFor(model => model.StartTimezone)
.HtmlAttributes(new { data_bind = "value:startTimezone" }))
</
div
>
<
div
class
=
"k-edit-label"
>
@Index.EndTimezone
</
div
>
<
div
data-container-for
=
"endTimezone"
class
=
"k-edit-field"
>
@(Html.Kendo().TimezoneEditorFor(model => model.EndTimezone)
.HtmlAttributes(new { data_bind = "value:endTimezone" }))
</
div
>
<
div
class
=
"k-edit-label"
>
@Index.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"
>
@Index.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"
>
@Index.Priority
</
div
>
<
div
data-container-for
=
"priority"
class
=
"k-edit-field"
>
@(Html.Kendo().NumericTextBoxFor(model => model.Priority)
.HtmlAttributes(new { data_bind = "value:Priority" })
.Min(0)
.Max(9)
.Format("n0")
)
</
div
>
<
div
class
=
"k-edit-label"
>
URL
</
div
>
<
div
data-container-for
=
"url"
class
=
"k-edit-field"
>
@(Html.TextBoxFor(model => model.Url, new { @class = "k-textbox", data_bind = "value:Url" }))
</
div
>
<
div
class
=
"k-edit-label"
>
@Index.Room
</
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" },
new { Text = "Meeting Room 304", Value = 3, Color = "\\#154afa" }
}).ToClientTemplate())
</
div
>
<
div
class
=
"k-edit-label"
>
@Index.Department
</
div
>
<
div
data-container-for
=
"DepartmentsID"
class
=
"k-edit-field"
>
@(Html.Kendo().MultiSelectFor(model => model.DepartmentsID)
.HtmlAttributes(new { data_bind = "value:DepartmentsID" })
.DataTextField("Text")
.DataValueField("Value")
//.ValuePrimitive(true)
.BindTo(new[] {
new { Text = "Department 101", Value = 1 },
new { Text = "Department 201", Value = 2 },
new { Text = "Department 304", Value = 3 }
})
)
</
div
>
<
div
class
=
"k-edit-label"
>
Externe
</
div
>
<
div
data-container-for
=
"Attendees"
class
=
"k-edit-field"
>
Adresse email
</
div
>
<
div
data-container-for
=
"Attendees"
class
=
"k-edit-field"
>
Nom
</
div
>
<
div
data-container-for
=
"Attendees"
class
=
"k-edit-field"
>
<
a
class
=
"k-button"
>
Ajouter à la liste
<
span
class
=
"icon-plus"
> </
span
>
</
a
>
</
div
>
<
script
>
$(document).ready(function () {
init();
});
function init() {
}
</
script
>
@{
ViewContext.FormContext = null;
}
So Url, Description, Title, RecurrenceRule, Priority,etc.. work pretty good, the right data were found in the TaskCreate function in the controller (TaskViewModel Task)
But the End, Start values have all the time the same value : {01/01/0001 00:00:00}.
And i can't have the right data for the IEnumerable<int> DepartmentsID, the IEnumareble is initialised but all this value equals 0.
I wonder if it's not a trouble of version. Maybe 2013.3.1511.440 add some bug ? Or am i maybe a fool ? I lost 3 day trying to accomplish this without any success.