jquery 模型未在Razor中的自定义HTML中绑定

mnemlml8  于 2023-06-22  发布在  jQuery
关注(0)|答案(1)|浏览(124)

各位开发者朋友,你们好,我刚刚学习ASP.NET Core MVC,现在我面临一个问题,在提交表单时模型没有与输入绑定。我创建了输入,特别是通过自定义HTML Helper创建的下拉按钮。
我已经尝试了不同的解决方案,但问题仍然存在。
下面是我的代码:

BootstrapHtml.cs

public static IHtmlContent BootstrapDropdownFor<TModel, TValue>(
this IHtmlHelper<TModel> htmlHelper, 
Expression<Func<TModel, TValue>> expression, 
IEnumerable<SelectListItem> list)
{
    var expressionHelper = htmlHelper.ViewContext.HttpContext.RequestServices.GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;
    var fieldName = expressionHelper.GetExpressionText(expression);
    var fullBindingName = htmlHelper.ViewContext.HttpContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
    var fieldId = TagBuilder.CreateSanitizedId(fullBindingName, "a");
    var metaData = expressionHelper.CreateModelExpression(htmlHelper.ViewData, expression);
    var value = metaData.Model;

    var button = new TagBuilder("input")
                     {  
                         Attributes = 
                             {
                                 { "id", fieldId },
                                 { "name", fullBindingName },
                                 { "type", "button" },
                                 { "data-bs-toggle", dropdown },
                                 { "value", value == null > string.empty : value.ToString() },
                             }
                     }

      var wrapper = new TagBuilder("div");
      wrapper.AddCssClass("dropdown");
   
      wrapper.InnerHtml.AppendHtml(button);
      button.InnerHtml.AppendHtml(BuildDropdownList(id, list));

      using (var writer = new StringWriter())
      {
          wrapper.WriteTo(writer, HtmlEncoder.Default);
          string asd = writer.ToString();
          return new HtmlString(asd);
      }
}

private static TagBuilder BuildDropdownList(string id, IEnumerable<SelectListItem> selectListItems) 
{
    var ul = new TagBuilder("ul")
                 { 
                     Attributes = 
                         {
                             { "class", "dropdown-menu" },
                             { "aria-labelledby", id }
                         }
                 };
    var listItem = new TagBuilder("li");
    listItem.Attributes.Add("class", "dropdown-item");
 
    foreach(var item in selectListItems)
    {
        var value = string.IsNullOrEmpty(item.value) ? string.Empty : item.Value;
        var disabledClass = item.Disabled ? "disabled" : string.Empty;
        ul.InnerHtml.AppendHtml($"<li value=\"{value}\" class=\"{disabledClass} dropdown-item\">" + $"<span>{item.Text}</span>" + "</li>");
    }
  
    return ul;
}

这就是我在Razor页面中使用上述元素的方式。

Test.cshtml

@model SomeModel

<form data-ajax="true" data-ajax-url="AreaName/ControllerName/ActionName" data-ajax-method="POST" data-ajax-success="OnSuccess(data)">

   @Html.BootstrapDropdownFor(a => a.DummyProperty, (IEnumerable<SelectListItem>)ViewData["ViewDataWithList"])

<button type="Submit">Create Record</button>
</form>

点击“创建记录”按钮后,我没有看到从自定义HTML中选择的值。在浏览器的开发工具>网络> FormData(来自API的有效负载)下进行验证。我假设自定义HTML没有绑定在“SomeModel”模型下的属性“DummyProperty”中。
任何帮助/提示/反馈都非常感谢。先谢谢你了🙂

ru9i0ody

ru9i0ody1#

我找不到任何htmlelemnt可以paresd到formdata当您提交表单

如果你想保持你的设计模式而不使用<select>,你需要一个隐藏的输入和一些js/jquery代码来保存你选择的值。
例如,我尝试如下:

public static class MyExtension
    {
        public static IHtmlContent BootstrapDropdownFor<TModel, TValue>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TValue>> expression,
IEnumerable<SelectListItem> list)
        {

            var expressionHelper = htmlHelper.ViewContext.HttpContext.RequestServices.GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;
            var fieldName = expressionHelper.GetExpressionText(expression);
            var fullBindingName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
            var fieldId = TagBuilder.CreateSanitizedId(fullBindingName, "a");
            var metaData = expressionHelper.CreateModelExpression(htmlHelper.ViewData, expression);
            var value = metaData.Model;

            var button = new TagBuilder("input")
            {
                Attributes =
                {
                  {"id", fieldId},
                  {"name", fullBindingName},
                  { "data-bs-toggle", "dropdown" },
                  {"type", "button"},
                  {"value", value == null ? "Select" : value.ToString()},
                  {"class", "myclass"}
                 }
            };
            var hiddeninput = new TagBuilder("input")
            {
                Attributes =
                {
                  {"id", fieldId+"hd"},
                  {"name", fullBindingName},
                  {"type", "text"},
                  {"hidden" ,"true"},
                  {"value","Value" },
                  {"class", "myclasshd"}
                }
            };

            var wrapper = new TagBuilder("div");
            wrapper.AddCssClass("dropdown");
            wrapper.InnerHtml.AppendHtml(button);
            wrapper.InnerHtml.AppendHtml(hiddeninput);
            button.InnerHtml.AppendHtml(BuildDropdownList(fieldId, list));

            using var writer = new StringWriter();

            wrapper.WriteTo(writer, HtmlEncoder.Default);
            string asd = writer.ToString();
            return new HtmlString(asd);

        }

        private static TagBuilder BuildDropdownList(string id, IEnumerable<SelectListItem> selectListItems)
        {

            var ul = new TagBuilder("ul")
            {
                Attributes =
                {
                 {"class", "dropdown-menu"},
                 {"aria-labelledby", id}
                 }
            };
            var listItem = new TagBuilder("li");
            listItem.Attributes.Add("class", "dropdown-item");

            foreach (var item in selectListItems)
            {
                var value = string.IsNullOrEmpty(item.Value) ? string.Empty : item.Value;
                var disabledClass = item.Disabled ? "disabled" : string.Empty;
                ul.InnerHtml.AppendHtml($"<li value=\"{value}\" class=\"{disabledClass} dropdown-item\">" + $"<span>{item.Text}</span>" + "</li>");
            }

            return ul;
        }
    }

型号:

public class SomeClass
    {
        public string? SomeProp { get; set; }
       
    }

浏览次数:

@model SomeClass
<form method="POST">

    @Html.BootstrapDropdownFor(a => a.SomeProp, new List<SelectListItem>(){
    new SelectListItem(){Text="Text1",Value="Text1"},
    new SelectListItem(){Text="Text2",Value="Text2"},
    new SelectListItem(){Text="Text3",Value="Text3"}
    })

    <button type="Submit">Create Record</button>
</form>

<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script>
    $("li.dropdown-item").click(function () {
        var val = $(this).children('span').html()
        console.log(val);
        $(".myclass").val(val)
        $(".myclasshd").val(val)
    })
</script>

结果:

相关问题