我有2个控制器字段,分别是“类型”和“数据”。 根据要为“类型”(日期或文本)选择的值,我想动态地将“数据”字段显示为文本输入或自定义时间选择器输入。 由于任何时候都只能渲染一个,因此我需要使用相同的属性名称(Data)进行绑定。 这就是我正在尝试的:
@if (Model.Type == "Date")
{
// custom timepicker control goes here
<input asp-for="Data" class="form-control timepicker"/>
}
else
{
<input asp-for="Data" class="form-control text-input" type="text"/>
}
在页面加载时,仅呈现文本输入,并且根据所选的类型显示/隐藏。不会显示时间选择器输入(根本不会生成html)。
有没有办法在MVC中实现这一目标?
答案 0 :(得分:1)
不能有两个具有相同名称的<input>
元素。如果发布的<form>
包含多个具有相同名称的输入,则MVC模型绑定程序将仅绑定来自最后一个输入的一个值。
要实现所需的目标,您有两种选择:
在视图中只有name="Data"
的{{1}}的一个输入,然后让时间选择器将时间作为字符串写入此输入。然后在控制器中,根据选定的type="text"
解析此输入值。
或者具有两个Type
和name="TextData"
输入,并根据选定的name="TimeData"
使用JS禁用和隐藏这些输入之一。在控制器中,根据所选的Type
从右侧输入中读取值。可以说这是更清洁的解决方案。
在MVC5中,第二个解决方案看起来像这样(我不熟悉MVC-Core):
Type
控制器:
@model MyViewModel
@using (Html.BeginForm("Submit", "MyController", FormMethod.Post)) {
@Html.EditorFor(m => m.Type)
@Html.EditorFor(m => m.TextData, new { @class = "text-input"})
@Html.EditorFor(m => m.TimeData, new { @class = "timepicker"})
}
<script type="text/javascript">
function toggleInput_() {
if ($('#@Html.IdFor(m => m.Type)').val() === 'Text') {
$('#@Html.IdFor(m => m.TextData)').prop('disabled', false).show();
$('#@Html.IdFor(m => m.TimeData)').prop('disabled', true).hide();
}
else {
$('#@Html.IdFor(m => m.TextData)').prop('disabled', true).hide();
$('#@Html.IdFor(m => m.TimeData)').prop('disabled', false).show();
}
}
$(document).ready(function() {
$('#@Html.IdFor(m => m.Type)').on('change', function() {
toggleInput_(); // toggle when drop down changes
});
toggleInput_(); // toggle initially on page load
});
</script>
答案 1 :(得分:1)
ASP MVC已经使用编辑器模板内置了此功能。通过遵循约定,您可以指定将用于@Html.EditorFor()
呈现的任何类型(包括用户定义的复杂类型)的模板。
简而言之,只需将两个局部视图放在~/Views/Shared/EditorTemplates
文件夹中,一个局部视图为模型类型DateTime
,另一个局部模型为string
。当基于@Html.EditorFor(m => m.Property)
的类型使用Property
时,将呈现正确的局部视图。
注意:string
属性的默认编辑器已经是type="text"
的输入,因此您不必指定该模板。
有关编辑器模板(和显示模板)的教程,请参见以下链接: https://exceptionnotfound.net/asp-net-mvc-demystified-display-and-editor-templates/