自定义Validation TagHelper:修改Kendo DatePicker子Input类实现服务端验证
问题:给Kendo DatePicker的子Input添加服务端验证错误类
我尝试用TagHelper实现服务端验证,目标是给Kendo DatePicker生成的子input标签添加is-invalid类,但现有代码只会修改外层span的类。试过GetChildContentAsync但没成功,相关代码和输出如下:
现有TagHelper代码
[HtmlTargetElement("kendo-datepicker")] [HtmlTargetElement("select")] [HtmlTargetElement("input")] public class ValidationErrorClassTagHelper : TagHelper { [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { if (context.TagName == "kendo-datepicker") { TagHelperAttribute taghelperAttribute = context.AllAttributes["for"]; if (taghelperAttribute != null) { ModelExpression modelExpression = (ModelExpression)taghelperAttribute.Value; ViewContext.ViewData.ModelState.TryGetValue(modelExpression.Name, out ModelStateEntry entry); if (entry != null && entry.Errors.Any()) { output.Attributes.SetAttribute("class", "form-control " + "is-invalid"); } } } } }
当前错误HTML输出
<span class="k-datepicker k-input form-control is-invalid k-input-solid k-input-md k-rounded-md" style=""> <input class="form-control k-input-inner valid" required="" data-val="true" data-val-required="Enter the date observed." id="ADR_Date" name="ADR.Date" type="text" value="6/07/2023" data-role="datepicker" role="combobox" aria-expanded="false" aria-haspopup="grid" aria-controls="ADR_Date_dateview" autocomplete="off" aria-disabled="false" aria-readonly="false" aria-describedby="ADR_Date-error" aria-invalid="false"> <button aria-label="select" tabindex="-1" class="k-input-button k-button k-icon-button k-button-md k-button-solid k-button-solid-base" type="button" role="button"> <span class="k-icon k-i-calendar k-button-icon"></span> </button> </span>
额外说明
Kendo的TagHelper不会直接渲染HTML结构,而是生成jQuery初始化脚本:
<script>kendo.syncReady(function(){jQuery("#ADR_Date").kendoDatePicker({"format":"d","value":new Date(2023,6,6,0,0,0,0)});});</script>
解决方案
Kendo DatePicker的TagHelper本质是生成前端初始化配置,而非直接输出HTML,所以无法通过服务端直接修改它的子元素。你需要通过Kendo自身的配置参数来传递样式类:
方案1:视图层直接动态配置
在使用kendo-datepicker的视图中,通过html-attributes结合ModelState动态添加错误类:
<kendo-datepicker for="ADR.Date" html-attributes='new { @class = ViewData.ModelState.IsValidField("ADR.Date") ? "form-control" : "form-control is-invalid" }'> </kendo-datepicker>
方案2:改进TagHelper配置传递
修改TagHelper,通过更新Kendo的html-attributes属性,让Kendo在生成input时自动带上错误类:
[HtmlTargetElement("kendo-datepicker")] public class ValidationErrorClassTagHelper : TagHelper { [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } // 绑定Kendo DatePicker的html-attributes属性 [HtmlAttributeName("html-attributes")] public IDictionary<string, object> HtmlAttributes { get; set; } = new Dictionary<string, object>(); public override void Process(TagHelperContext context, TagHelperOutput output) { var forAttr = context.AllAttributes["for"]; if (forAttr == null) return; var modelExpression = (ModelExpression)forAttr.Value; if (ViewContext.ViewData.ModelState.TryGetValue(modelExpression.Name, out var entry) && entry.Errors.Any()) { // 合并已有类和错误类 if (HtmlAttributes.TryGetValue("class", out var existingClass)) { HtmlAttributes["class"] = $"{existingClass} is-invalid"; } else { HtmlAttributes["class"] = "form-control is-invalid"; } // 更新输出的html-attributes属性 output.Attributes.SetAttribute("html-attributes", HtmlAttributes); } } }
原理说明
Kendo的TagHelper会将html-attributes中的配置传递给前端初始化代码,最终生成的input元素会带上这些样式类。之前的错误在于直接修改了外层容器span的类,而我们需要的是给内部input配置样式,必须通过Kendo的参数传递才能生效。
内容的提问来源于stack exchange,提问作者Reafidy
相关产品推荐
相关产品推荐

