MVC EditorTemplate with multiple inputs for the same value
I have crea开发者_Python百科ted this editor template:
@model DateTime?
@using MyMvcApp.Properties
<div id="dateTimePicker_@(ViewData.ModelMetadata.PropertyName)">
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function () {
var $div = $('#dateTimePicker_@(ViewData.ModelMetadata.PropertyName)');
$div.find('.date').datepicker({ altFormat: 'dd-mm-yy' });
});
function clearDateTimePicker_@(ViewData.ModelMetadata.PropertyName)() {
var $div = $('#dateTimePicker_@(ViewData.ModelMetadata.PropertyName)');
$div.find('.date').val('');
$div.find('.hour').val('00');
$div.find('.minute').val('00');
}
//]]>
</script>
@* Date - should equal DatePicker.cshtml *@
@Html.TextBox("Value.Date", Model.HasValue ? Model.Value.Date.ToString() : string.Empty, new { @class = "date" })
<img alt="@Resources.SelectDate" src="../../../images/calendar.png" class="calendarIcon" />
@* Time - should equal TimePicker.cshtml *@
@Html.DropDownList("Value.Hour", new SelectList(new[] { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23" }, Model.HasValue ? Model.Value.Hour.ToString("D2") : "00"),
null, new { style = "width: auto; margin-left: 5px;", @class = "hour" })
:
@{
List<string> availableMinutes = new List<string>();
for (int minute = 0; minute < 60; minute += 1)
{
availableMinutes.Add(minute.ToString("D2"));
}
@Html.DropDownList("Value.Minute", new SelectList(availableMinutes, Model.HasValue ? Model.Value.Minute.ToString("D2") : "00"),
null, new { style = "width: auto;", @class = "minute" });
}
<img alt="@Resources.SelectTime" src="../../../images/icon_clock_2.gif" style="margin-right: 5px" />
<input type="button" value="@Resources.Clear" class="ui-state-default" onclick="javascript:clearDateTimePicker_@(ViewData.ModelMetadata.PropertyName)()" />
</div>
As you can see, what I am trying to accomplish is that the user can enter a date/time. However, as input I want to use DateTime? (nullable) because it might be possible the user doesn't want to select ANY date/time.
This EditorTemplate does not work when the input model is null. Is there any way to create an EditorTemplate that accepts null values and then can still fill the value if entered by the user?
Ok, I finally nailed down the problem. My solution in words:
I use a hidden field that stores the current value in textual representation. This hidden field is always translated to the model itself (then it correctly translates to null or a value including hour and minutes). Every time an input element is changed, I update the local value which is being posted back to the server.
My solution in code:
@model DateTime?
@using Narcast.Server.Properties
<div id="dateTimePicker_@(ViewData.ModelMetadata.PropertyName)">
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function () {
var $div = $('#dateTimePicker_@(ViewData.ModelMetadata.PropertyName)');
$div.find('.date').datepicker({ altFormat: 'dd-mm-yy' });
});
function clearDateTimePicker_@(ViewData.ModelMetadata.PropertyName)() {
var $div = $('#dateTimePicker_@(ViewData.ModelMetadata.PropertyName)');
$div.find('.date').val('');
$div.find('.hour').val('00');
$div.find('.minute').val('00');
updateData_@(ViewData.ModelMetadata.PropertyName)();
}
function updateData_@(ViewData.ModelMetadata.PropertyName)() {
var $div = $('#dateTimePicker_@(ViewData.ModelMetadata.PropertyName)');
var $date = $div.find('.date').val();
var $hour = $div.find('.hour').val();
var $minute = $div.find('.minute').val();
var $data = '';
if ($date != '')
{
$data = $date + ' ' + $hour + ':' + $minute;
}
$div.find('.data').val($data);
}
//]]>
</script>
@* Hidden field holding the client data *@
@Html.Hidden("", Model.HasValue ? Model.Value.ToShortTimeString() : string.Empty, new { @class = "data" })
@* Date - should equal DatePicker.cshtml *@
<input type="text" class="date" onchange="javascript:updateData_@(ViewData.ModelMetadata.PropertyName)()" />
@*@Html.TextBox("Date", Model.HasValue ? Model.Value.Date.ToString() : string.Empty, new { @class = "date" })*@
<img alt="@Resources.SelectDate" src="../../../images/calendar.png" class="calendarIcon" />
@* Time - should equal TimePicker.cshtml *@
<select class="hour" style="width: auto; margin-left: 5px;" onchange="javascript:updateData_@(ViewData.ModelMetadata.PropertyName)()">
@{
for (int hour = 0; hour < 24; hour += 1)
{
<text><option @{ if (Model.HasValue && Model.Value.Hour == hour) { <text>selected="selected"</text> }}>@(hour.ToString("D02"))</option></text>
}
}
</select>
:
<select class="minute" style="width: auto; margin-left: 5px;" onchange="javascript:updateData_@(ViewData.ModelMetadata.PropertyName)()">
@{
for (int minute = 0; minute < 60; minute += 1)
{
<text><option @{ if (Model.HasValue && Model.Value.Minute == minute) { <text>selected="selected"</text> }}>@(minute.ToString("D02"))</option></text>
}
}
</select>
<img alt="@Resources.SelectTime" src="../../../images/icon_clock_2.gif" style="margin-right: 5px" />
<input type="button" value="@Resources.Clear" class="ui-state-default" onclick="javascript:clearDateTimePicker_@(ViewData.ModelMetadata.PropertyName)()" />
</div>
精彩评论