ASP.Net MVC 动态输入绑定到同一控制器 属性
ASP.Net MVC Dynamic input bound to same controller property
我有 2 个控制器字段,分别是类型和数据。
根据为类型(日期或文本)选择的值,我想将数据字段动态显示为文本输入或自定义时间选择器输入。
由于任何时候只会渲染一个,因此我需要使用相同的 属性 名称(数据)进行绑定。
这就是我正在尝试的:
@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"/>
}
在页面加载时仅呈现文本输入,并且它 shows/hides 基于所选的类型。 timepicker 输入永远不会显示(根本不会生成 html)。
有没有办法在 MVC 中实现这一点?
不能有两个同名的 <input>
元素。如果发布包含多个同名输入的 <form>
,则 MVC 模型绑定器将仅绑定最后一个输入中的一个值。
要实现你想要的,你有两个选择:
要么在视图中只有一个输入 name="Data"
或 type="text"
,然后让时间选择器将时间作为字符串写入此输入。然后在控制器中,根据选择的 Type
.
解析这个输入值
或者有两个输入 name="TextData"
和 name="TimeData"
,并根据所选 Type
使用 JS 禁用和隐藏其中一个输入。在控制器中,根据所选 Type
从右侧输入读取值。这可以说是更清洁的解决方案。
在 MVC5 中,第二种解决方案如下所示(我不熟悉 MVC-Core):
@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>
控制器:
[HttPost]
public ActionResult Submit(MyViewModel postData) {
string textValue = null;
DateTime? timeValue = null;
if (postData.Type == "Text") {
textValue = postData.TextData;
}
else {
timeValue = postData.TimeData;
}
// ...
}
ASP MVC 已经通过 编辑器模板 内置了此功能。按照约定,您可以指定一个模板用于将使用 @Html.EditorFor()
.
呈现的任何类型(包括用户定义的复杂类型)
简而言之,只需将两个局部视图放在 ~/Views/Shared/EditorTemplates
文件夹中,一个模型类型为 DateTime
,另一个为 string
。根据 Property
.
的类型使用 @Html.EditorFor(m => m.Property)
时将呈现正确的局部视图
注意:string
属性 的默认编辑器已经是 type="text"
的输入,因此您不一定需要指定该模板.
有关编辑器模板(和显示模板)的教程,请参阅此 link:
https://exceptionnotfound.net/asp-net-mvc-demystified-display-and-editor-templates/
我有 2 个控制器字段,分别是类型和数据。 根据为类型(日期或文本)选择的值,我想将数据字段动态显示为文本输入或自定义时间选择器输入。 由于任何时候只会渲染一个,因此我需要使用相同的 属性 名称(数据)进行绑定。 这就是我正在尝试的:
@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"/>
}
在页面加载时仅呈现文本输入,并且它 shows/hides 基于所选的类型。 timepicker 输入永远不会显示(根本不会生成 html)。
有没有办法在 MVC 中实现这一点?
不能有两个同名的 <input>
元素。如果发布包含多个同名输入的 <form>
,则 MVC 模型绑定器将仅绑定最后一个输入中的一个值。
要实现你想要的,你有两个选择:
要么在视图中只有一个输入
name="Data"
或type="text"
,然后让时间选择器将时间作为字符串写入此输入。然后在控制器中,根据选择的Type
. 解析这个输入值
或者有两个输入
name="TextData"
和name="TimeData"
,并根据所选Type
使用 JS 禁用和隐藏其中一个输入。在控制器中,根据所选Type
从右侧输入读取值。这可以说是更清洁的解决方案。
在 MVC5 中,第二种解决方案如下所示(我不熟悉 MVC-Core):
@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>
控制器:
[HttPost]
public ActionResult Submit(MyViewModel postData) {
string textValue = null;
DateTime? timeValue = null;
if (postData.Type == "Text") {
textValue = postData.TextData;
}
else {
timeValue = postData.TimeData;
}
// ...
}
ASP MVC 已经通过 编辑器模板 内置了此功能。按照约定,您可以指定一个模板用于将使用 @Html.EditorFor()
.
简而言之,只需将两个局部视图放在 ~/Views/Shared/EditorTemplates
文件夹中,一个模型类型为 DateTime
,另一个为 string
。根据 Property
.
@Html.EditorFor(m => m.Property)
时将呈现正确的局部视图
注意:string
属性 的默认编辑器已经是 type="text"
的输入,因此您不一定需要指定该模板.
有关编辑器模板(和显示模板)的教程,请参阅此 link: https://exceptionnotfound.net/asp-net-mvc-demystified-display-and-editor-templates/