我有一个包含 ICustomInput 值列表的模型视图
public class DemoViewModel {
[Required]
public string FirstName {get; set;}
[Required]
public string LastName {get; set;}
[RequiredIf("DayPhoneRequired", true)]
public string DayPhone {get; set;}
public bool DayPhoneRequired {get; set;} = false;
public List<ICustomInput> CustomInputFields { get; set; } = new List<ICustomInput>();
}
ICustomInput 的示例
public class CustomTextInput : ICustomInput
{
public CustomField Field { get; }
public string DisplayName { get; set; }
[RequiredIf("DataValueRequired", true, ErrorMessage = "This is a required field")]
public virtual string DataValue { get; set; }
public bool DataValueRequired { get; set; } = false;
public virtual string ClassName => "CustomTextInput";
public string AssemblyName => "Application.Models";
}
这样做的目的是让我可以从数据库中提取有关已登录客户端在表单上请求的自定义输入字段的信息。一个客户可能想要几个文本字段,另一个客户可能想要一个下拉菜单。这些自定义字段可能需要也可能不需要输入。(CustomField 对象是由 dataLayer 返回的旧对象,并且被大量使用,我不想重建它,但假设它只是充满了字符串)
我有一个用于 ICustomInputs 的具体实现的编辑器模板以及允许我在发布时获取数据的自定义活页夹。但我遇到的问题是,RequiredIf 属性将客户端验证的不显眼数据值设置为所有 ICustomInputs 相同。这是有道理的,因为它们的依赖属性都具有相同的名称,但这并不能解决我遇到的问题。
我的视图通过简单地显示 ICustomInput 列表:
@Html.EditorFor(model => model.CustomInputFields)
然后,实现 ICustomInput 的每个具体类型都有自己的 editorTemplate,类似于:
<div class="columnPositioner">
<div class="inputContainer">
@Html.TextBoxFor(model => model.DataValue, new
{
@class = "inputFields input-lg form-control",
placeholder = Model.Field.Display
})
<span class="inputLabel">
@Html.LabelFor(model => model.Field.Display, Model.Field.Display)
</span>
@Html.ValidationMessageFor(model => model.DataValue, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.DataValueRequired)
</div>
</div>
生成的 HTML 如下所示:
<select name="CustomInputFields[0].DataValue" class="inputFields input-lg form-control" id="CustomInputFields_0__DataValue" data-val="true" data-val-requiredif-operator="EqualTo" data-val-requiredif-dependentvalue="True" data-val-requiredif-dependentproperty="DataValueRequired" data-val-requiredif="This is a required field"><option value="">TEST01</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
</select>
<input name="CustomInputFields[0].DataValueRequired" class="hasContent" id="CustomInputFields_0__DataValueRequired" type="hidden" value="True" data-val-required="The DataValueRequired field is required." data-val="true">
<input name="CustomInputFields[1].DataValue" class="inputFields input-lg form-control" id="CustomInputFields_1__DataValue" type="text" placeholder="TEST02" value="" data-val="true" data-val-requiredif-operator="EqualTo" data-val-requiredif-dependentvalue="True" data-val-requiredif-dependentproperty="DataValueRequired" data-val-requiredif="This is a required field">
<input name="CustomInputFields[1].DataValueRequired" id="CustomInputFields_1__DataValueRequired" type="hidden" value="False" data-val-required="The DataValueRequired field is required." data-val="true">
隐藏字段已正确命名,但是如何获取属性以将 data-val-requiredif-dependentproperty 设置为隐藏字段上的实际 ID/名称?
我目前没有列表的自定义编辑器模板。我确实有一个,但无法让它正确绑定数据。将编辑器模板放在 List 上并为 ICustomInput 的具体实现构建唯一的编辑器模板为我提供了所需的所有 UI 布局控件并正确绑定数据,但现在我无法让客户端验证正常工作。如果它只是一个编辑器模板,那会是什么样子?
更新
这是一个修复,但我不喜欢它。我有一个 javascript,它已经通过输入执行 .each 以应用样式,所以我将它添加到 .each:
function requiredIfHack($input) {
var depPropVal = $input.data("val-requiredif-dependentproperty");
//return if the value exists
if ($("#" + depPropVal).length) return;
//it doesn't. it's missing the parent object name
var parentName = $input.attr("name").split(".")[0].replace("[", "_").replace("]", "_");
$input.data("val-requiredif-dependentproperty", parentName + "_" + depPropVal);
}
它解决了问题,但我认为这不应该是js负责解决的问题。而且由于这是一个非常偷偷摸摸的修复,它可能会绊倒其他试图在未来处理此代码的人。我仍然想找到更好的方法来做到这一点。