asp.net mvc: why is Html.CheckBox generating an additional hidden input

后端 未结 11 1870
猫巷女王i
猫巷女王i 2020-11-22 13:59

I just noticed that Html.CheckBox(\"foo\") generates 2 inputs instead of one, anybody knows why is this so ?



        
相关标签:
11条回答
  • 2020-11-22 14:39

    The hidden input was causing problems with styled checkboxes. So I created a Html Helper Extension to place the hidden input outside the div containing the CheckBox.

    using System;
    using System.Linq.Expressions;
    using System.Text;
    using System.Web.Mvc;
    using System.Web.Routing;
    
    namespace YourNameSpace
    {
        public static class HtmlHelperExtensions
        {
            public static MvcHtmlString CustomCheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string labelText)
            {
                //get the data from the model binding
                var fieldName = ExpressionHelper.GetExpressionText(expression);
                var fullBindingName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
                var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);
                var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
                var modelValue = metaData.Model;
    
                //create the checkbox
                TagBuilder checkbox = new TagBuilder("input");
                checkbox.MergeAttribute("type", "checkbox");
                checkbox.MergeAttribute("value", "true"); //the visible checkbox must always have true
                checkbox.MergeAttribute("name", fullBindingName);
                checkbox.MergeAttribute("id", fieldId);
    
                //is the checkbox checked
                bool isChecked = false;
                if (modelValue != null)
                {
                    bool.TryParse(modelValue.ToString(), out isChecked);
                }
                if (isChecked)
                {
                    checkbox.MergeAttribute("checked", "checked");
                }
    
                //add the validation
                checkbox.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fieldId, metaData));
    
                //create the outer div
                var outerDiv = new TagBuilder("div");
                outerDiv.AddCssClass("checkbox-container");
    
                //create the label in the outer div
                var label = new TagBuilder("label");
                label.MergeAttribute("for", fieldId);
                label.AddCssClass("checkbox");
    
                //render the control
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(outerDiv.ToString(TagRenderMode.StartTag));
                sb.AppendLine(checkbox.ToString(TagRenderMode.SelfClosing));
                sb.AppendLine(label.ToString(TagRenderMode.StartTag));
                sb.AppendLine(labelText); //the label
                sb.AppendLine("<svg width=\"10\" height=\"10\" class=\"icon-check\"><use xlink:href=\"/icons.svg#check\"></use></svg>"); //optional icon
                sb.AppendLine(label.ToString(TagRenderMode.EndTag));
                sb.AppendLine(outerDiv.ToString(TagRenderMode.EndTag));
    
                //create the extra hidden input needed by MVC outside the div
                TagBuilder hiddenCheckbox = new TagBuilder("input");
                hiddenCheckbox.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
                hiddenCheckbox.MergeAttribute("name", fullBindingName);
                hiddenCheckbox.MergeAttribute("value", "false");
                sb.Append(hiddenCheckbox.ToString(TagRenderMode.SelfClosing));
    
                //return the custom checkbox
                return MvcHtmlString.Create(sb.ToString());
            }
    

    Result

    <div class="checkbox-container">
        <input checked="checked" id="Model_myCheckBox" name="Model.myCheckBox" type="checkbox" value="true">
        <label class="checkbox" for="Model_myCheckBox">
            The checkbox label
            <svg width="10" height="10" class="icon-check"><use xlink:href="/icons.svg#check"></use></svg>
        </label>
    </div>
    <input name="Model.myCheckBox" type="hidden" value="false">
    
    0 讨论(0)
  • 2020-11-22 14:43

    when the check box is checked and submitted perform this

    if ($('[name="foo"]:checked').length > 0)
        $('[name="foo"]:hidden').val(true);
    

    Refer

    0 讨论(0)
  • 2020-11-22 14:45

    Use Contains, it will work with the two possible post values: "false" or "true,false".

    bool isChecked = Request.Form["foo"].Contains("true");
    
    0 讨论(0)
  • 2020-11-22 14:46

    This is the strongly typed version of Alexander Trofimov's solution:

    using System.Web.Mvc;
    using System.Web.Mvc.Html;
    
    public static class HelperUI
    {
        public static MvcHtmlString CheckBoxSimpleFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes)
        {
            string checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
            string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
            return new MvcHtmlString(pureCheckBox);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 14:46

    This is not a bug! It adds the possibility of having always a value, after posting the form to the server. If you want to deal with checkbox input fields with jQuery, use the prop method (pass the 'checked' property as the parameter). Example: $('#id').prop('checked')

    0 讨论(0)
  • 2020-11-22 14:46

    You can try to initialize the constructor of your Model like that :

    public MemberFormModel() {
        foo = true;
    }
    

    and in your view :

    @html.Checkbox(...)
    @html.Hidden(...)
    
    0 讨论(0)
提交回复
热议问题