Search code examples
javascriptasp.net-mvcdatetimepickerbootstrap-datetimepickermvc-editor-templates

Bootstrap 3 DateTimePicker in EditorTemplate


Created an Editor Template to dynamically create time slots. Now I am unable to select the time with datetimepicker. Code below. The following code works when apart of the main view. Is it possible to use datetimepicker in an editortemplate?

@model Testing.Models.TimeSlot

<div class="form-group row">
    @Html.LabelFor(model => model.StartTime, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-2">
        @Html.EditorFor(model => model.StartTime, new { htmlAttributes = new { @Value = DateTime.Now.ToString("hh:mm tt"), @class = "form-control", @style = "width: 100px"} })
        @Html.ValidationMessageFor(model => model.StartTime, "", new { @class = "text-danger" })
    </div>
    @Html.LabelFor(model => model.EndTime, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-2">
        @Html.EditorFor(model => model.EndTime, new { htmlAttributes = new { @Value = DateTime.Now.AddMinutes(15).ToString("hh:mm tt"), @class = "form-control", @style = "width: 100px" } })
        @Html.ValidationMessageFor(model => model.EndTime, "", new { @class = "text-danger" })
    </div>
</div>


@section Scripts
{
<script type="text/javascript">
    $(function () {
        $('#StartTime').datetimepicker({

            format: 'LT',
            showClose: true,
            showClear: true,
            toolbarPlacement: 'top',
            stepping: 15,
        });
    });
    $(function () {
        $('#EndTime').datetimepicker({

            format: 'LT',
            showClose: true,
            showClear: true,
            toolbarPlacement: 'top',
            stepping: 15
        });
    });
    $('#StartTime').removeAttr("data-val-date");
    $('#EndTime').removeAttr("data-val-date");
</script>

Solution

  • Sections are not supported in partials, and your scripts are never included in the html returned to the client. In any case, scripts should never be in partials (which is what an EditorTemplate is) - you are generating inline scripts, making it harder to debug and risk including multiple instances of the scripts.

    Delete the @section Scripts{ ... } code from your EditorTemplate and move it to the main view or its layout. To make this a bit more flexible, I recommend you give the inputs a class name, and use that as a jQuery selector, rather that referring to each individual id (and therefore only one script is required).

    In addition, you should never set the value attribute when using the HtmlHelper methods. The methods correctly generate the value from ModelState, ViewData and finally the model property in that order, and by setting the value attribute, you are screwing up model binding. Instead, set the values in the GET method before you pass the model to the view.

    Your code to generate the datepicker should be just

    @Html.EditorFor(m => m.StartTime, new { htmlAttributes = new { @class = "form-control datetimepicker" } })
    

    or more simply

    @Html.TextBoxFor(m => m.StartTime, new { @class = "form-control datetimepicker" })    
    

    and you can then style the width

    .datetimepicker {
        width: 100px;
    }
    

    and the the script in the view or layout will be just

    $('.datetimepicker').datetimepicker({
        format: 'LT',
        showClose: true,
        showClear: true,
        toolbarPlacement: 'top',
        stepping: 15,
    });
    

    Its also not clear why you want to attempt to remove client side validation using .removeAttr("data-val-date"), and doing so suggests a problem with your design. It also appears that you want to select a time only, in which case your property should be TimeSpan.