Telerik调度程序自定义编辑器DateTimePicker营业时间,默认值和双重预订

时间:2015-09-17 18:20:34

标签: asp.net-mvc telerik-mvc telerik-scheduler

ASP.Net的Telerik UI非常有用,但文档有时可能不完整或不清楚。 Scheduler最初很容易实现,但是定制它可能很困难。 我需要一个自定义编辑器,其中包含与内置编辑器不同的字段,我需要对事件开始时间和事件结束时间进行自定义限制,例如创建新约会,但是在打开时不应影响现有约会:

  1. 下拉DateTimePicker中提供的开始和结束时间必须反映我们的营业时间(9:00 - 21:00),但是剑道助手会全天24小时生成。
  2. 选择开始时间后,结束时间必须在开始时间之后,DateTimePicker应自动设置为选定的开始时间值。
  3. 约会时段不能预订两次。

1 个答案:

答案 0 :(得分:2)

我花了一些时间来处理这些要求,通过Telerik的博客,论坛,演示,API文档以及提交支持的门票,我已经能够完成所有这些。它们比应该更难,因为它们放置在调度程序的自定义编辑器中,这是部分视图,并且因为它们依赖于调度程序本身的触发事件。您需要的大多数信息都可以通过调度程序中的事件传递,但困难在于查找有关它们的文档。 我在编辑器中有2个DateTimePickers,开始和结束时间:

<div data-container-for="start" class="k-edit-field">

   @(Html.Kendo().DateTimePickerFor(model => model.Start)
    .Name("start")
    .HtmlAttributes(generateDatePickerAttributes("startDateTime", "start", "value:start"))
    )
<span data-for="start" class="k-invalid-msg"></span>
</div>
<div class="k-edit-label">
    @(Html.Label("End Time*"))
</div>
 <div data-container-for="end" class="k-edit-field">
    @(Html.Kendo().DateTimePickerFor(model => model.End)
    .Name("end")
    .HtmlAttributes(generateDatePickerAttributes(
        "endDateTime",
        "end",
        "value:end",
                new Dictionary<string, object>() { { "data-dateCompare-msg", "End date should be greater than or equal to the start date" } }))
       )
   <span data-for="end" class="k-invalid-msg"></span>
</div>

使用此方法为他们提供适当的Kendo属性:

@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;";
    datePickerAttributes["data-role"] = "datetimepicker";

    return datePickerAttributes;
}
}
  1. 为了让DateTimePicker反映营业时间,我订阅了调度程序的Edit event(不要忘记在调度程序事件规范中引用它),然后使用setOptions()方法:

    function onEdit(e) {//When we open or add an event
        var min = new Date(kendo.date.getDate(new Date()).getTime() +    (kendo.date.MS_PER_HOUR * 9));
        var max = new Date(kendo.date.getDate(new Date()).getTime() + (kendo.date.MS_PER_HOUR * 21));
    
        e.container.find("[data-role=datetimepicker]").each(function () {
            var widget = $(this).getKendoDateTimePicker();
            widget.timeView.setOptions({
            max: max,
            min: min
        });
    
       });
      }
    
  2. 您可以将onChange()函数绑定到DateTimePicker本身,以强制结束时间始终使用以下代码反映&gt; =开始时间,同样在onEdit()方法中调度。它还处理在选择器中更改实际日期(而不仅仅是时间)并使其保持在工作时间内的情况。如果没有这一点,最小时间仍然是你最初设定的时间意味着第二天它将再次显示所有24小时。:

       e.container.find("[name=start][data-role=datetimepicker]").bind("change",    function () {
        var widget = $(this).getKendoDateTimePicker();
        widget.timeView.setOptions({
            max: max,
            min: min
        });
    
        var endTimePicker = $("#endDateTime").data("kendoDateTimePicker");
        endTimePicker.value(widget.value());
        endPicker = e.container.find("[name=end][data-role=datetimepicker]").getKendoDateTimePicker();
        endPicker.timeView.setOptions({
            max: max,
            min: min
        });
    });
    e.container.find("[name=end][data-role=datetimepicker]").bind("change", function () {
        var widget = $(this).getKendoDateTimePicker();
        widget.timeView.setOptions({
            max: max,
            min: min
        });
    });
    
  3. 检查双重预订并不像您想象的那样复杂,因为它不需要任何服务器调用,获得所有约会,检查时间范围和返回。 Telerik有一种检查调度程序中约会的方法。这是一种方便他们不能很好地记录的方法:occurrencesInRange()。我在其中一个论坛演示中找到了它。您可以在您想要使用的时间范围内获取所有事件,如果没有其他人使用它,请预订该事件。如果是,您只需显示提醒即可。订阅计划程序Save event

    function scheduler_save(e){     if(!checkAvailability(e.event.start,e.event.end,e.event)){         警告(&#34;此约会时段已被采用。安排不同的时间。&#34;);         e.preventDefault();     } } function checkAvailability(start,end,event){     var scheduler = $(&#34;#scheduler&#34;)。getKendoScheduler();

    var occurrences = scheduler.occurrencesInRange(start, end);
    var idx = occurrences.indexOf(event);
    if (idx > -1) {
        occurrences.splice(idx, 1);
    }
    return !occurrences.length;
    }
    
  4. 您可能遇到的另一个问题是让DateTimePicker仅包含营业时间,但默认值为当天的00:00:00,当然,这超出了您的范围。这非常难以默认为营业时间开始,但您可以使用其他非常有用的方法event.isNew()来执行以下操作:

    if (e.event.isNew()) {
        var startdate = e.event.start;
        startdate.setHours(9);
        var start = e.container.find("[name=start][data-role=datetimepicker]");
        var end = e.container.find("[name=end][data-role=datetimepicker]");
        $(start).data("kendoDateTimePicker").value(startdate); 
        $(end).data("kendoDateTimePicker").value(startdate);
     }
    

    这是最终的JavaScript方法集:

    function onEdit(e) {//When we open or add an event
       var min = new Date(kendo.date.getDate(new Date()).getTime() + (kendo.date.MS_PER_HOUR * 9));
       var max = new Date(kendo.date.getDate(new Date()).getTime() + (kendo.date.MS_PER_HOUR * 21));
       if (e.event.isNew()) {
           var startdate = e.event.start;
           startdate.setHours(9);
           var start = e.container.find("[name=start][data-role=datetimepicker]");
           var end = e.container.find("[name=end][data-role=datetimepicker]");
           $(start).data("kendoDateTimePicker").value(startdate);
           $(end).data("kendoDateTimePicker").value(startdate); 
       }
       e.container.find("[data-role=datetimepicker]").each(function () {
           var widget = $(this).getKendoDateTimePicker();
           widget.timeView.setOptions({
              max: max,
               min: min
           });
    
       });
        e.container.find("[name=start][data-role=datetimepicker]").bind("change", function () {
           var widget = $(this).getKendoDateTimePicker();
           widget.timeView.setOptions({
              max: max,
              min: min
          });
    
          var endTimePicker = $("#endDateTime").data("kendoDateTimePicker");
          endTimePicker.value(widget.value());
          endPicker = e.container.find("[name=end][data-role=datetimepicker]").getKendoDateTimePicker();
          endPicker.timeView.setOptions({
              max: max,
              min: min
          });
       });
       e.container.find("[name=end][data-role=datetimepicker]").bind("change",    function () {
            var widget = $(this).getKendoDateTimePicker();
            widget.timeView.setOptions({
                max: max,
                min: min
            });
        });
    }
    function scheduler_save(e) {
        if (!checkAvailability(e.event.start, e.event.end, e.event)) {
          alert("This appointment slot is taken. Schedule a different time.");
          e.preventDefault();
      }
      }
      function checkAvailability(start, end, event) {
           var scheduler = $("#scheduler").getKendoScheduler();
    
            var occurrences = scheduler.occurrencesInRange(start, end);
            var idx = occurrences.indexOf(event);
            if (idx > -1) {
                occurrences.splice(idx, 1);
            }
            return !occurrences.length;
         }
    
  5. 我希望这能节省20个小时的其他人。

    资料来源:http://www.telerik.com/forums/set-default-time-in-scheduler-editor-window-when-adding-task-in-month-view

    http://docs.telerik.com/KENDO-UI/api/javascript/ui/datetimepicker#events

    http://docs.telerik.com/KENDO-UI/api/aspnet-mvc/kendo.mvc.ui.fluent/schedulerbuilder

    http://www.telerik.com/forums/how-to-check-for-double-reservations-overlap-(repeating-events) Vladimir Illiev,Telerick DateTimePicker专家