ฉันเพิ่งสังเกตเห็นว่าHtml.CheckBox("foo")
สร้าง 2 อินพุตแทนที่จะเป็นหนึ่งใครรู้ว่าทำไมถึงเป็นเช่นนั้น?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
ฉันเพิ่งสังเกตเห็นว่าHtml.CheckBox("foo")
สร้าง 2 อินพุตแทนที่จะเป็นหนึ่งใครรู้ว่าทำไมถึงเป็นเช่นนั้น?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
คำตอบ:
หากไม่ได้เลือกช่องทำเครื่องหมายจะไม่มีการส่งฟิลด์แบบฟอร์ม นั่นคือเหตุผลที่มีค่าเท็จเสมอในฟิลด์ที่ซ่อนอยู่ หากคุณไม่เลือกช่องทำเครื่องหมายฟอร์มจะยังคงมีค่าจากฟิลด์ที่ซ่อนอยู่ นั่นคือวิธีที่ ASP.NET MVC จัดการกับค่าช่องทำเครื่องหมาย
หากคุณต้องการที่จะยืนยันว่าวางช่องทำเครื่องหมายลงในแบบฟอร์มไม่ได้อยู่กับ Html.Hidden <input type="checkbox" name="MyTestCheckboxValue"></input>
แต่มี ไม่ต้องทำเครื่องหมายที่ช่องทำเครื่องหมายส่งแบบฟอร์มและดูค่าคำขอที่โพสต์ทางฝั่งเซิร์ฟเวอร์ คุณจะเห็นว่าไม่มีค่าช่องทำเครื่องหมาย หากคุณมีเขตข้อมูลที่ซ่อนอยู่ก็จะมีMyTestCheckboxValue
รายการที่มีfalse
ค่า
IsActive
ซึ่งเริ่มต้นtrue
ใน constructor ผู้ใช้ไม่ได้เลือกช่องทำเครื่องหมาย แต่เนื่องจากค่าไม่ถูกส่งไปยังเซิร์ฟเวอร์ตัวยึดโมเดลจะไม่มารับและค่าคุณสมบัติจะไม่เปลี่ยนแปลง Model binder ไม่ควรสันนิษฐานว่าหากไม่มีการส่งค่ามันจะถูกตั้งค่าเป็นเท็จเพราะอาจเป็นการตัดสินใจของคุณที่จะไม่ส่งค่านี้
false
ค่าแม้ว่าจะถูกตรวจสอบและนั่นทำให้เกิดความสับสน ช่องทำเครื่องหมายที่ปิดใช้งานไม่ควรส่งค่าใด ๆ เลยถ้า ASP.NET ต้องการให้เข้ากันได้กับลักษณะการทำงาน HTTP เริ่มต้น
คุณสามารถเขียนผู้ช่วยเพื่อป้องกันการเพิ่มอินพุตที่ซ่อนอยู่:
using System.Web.Mvc;
using System.Web.Mvc.Html;
public static class HelperUI
{
public static MvcHtmlString CheckBoxSimple(this HtmlHelper htmlHelper, string name, object htmlAttributes)
{
string checkBoxWithHidden = htmlHelper.CheckBox(name, htmlAttributes).ToHtmlString().Trim();
string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
return new MvcHtmlString(pureCheckBox);
}
}
ใช้มัน:
@Html.CheckBoxSimple("foo", new {value = bar.Id})
@using Your.Name.Space
ที่ด้านบนของไฟล์มุมมอง. cshtml ของคุณ
System.Web.Mvc.Html
ให้สามารถเข้าถึงได้ในทุกมุมมอง
เมื่อทำเครื่องหมายในช่องทำเครื่องหมายและส่งข้อมูลดำเนินการ
if ($('[name="foo"]:checked').length > 0)
$('[name="foo"]:hidden').val(true);
คู่มือวิธีการคือ:
bool IsDefault = (Request.Form["IsDefault"] != "false");
นี่เป็นวิธีแก้ปัญหาของ Alexander Trofimov ที่ได้รับการตีพิมพ์อย่างมาก:
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);
}
}
ใช้มี, มันจะทำงานกับค่าโพสต์ที่เป็นไปได้สองค่า: "false" หรือ "true, false"
bool isChecked = Request.Form["foo"].Contains("true");
อินพุตที่ซ่อนอยู่ก่อให้เกิดปัญหากับช่องทำเครื่องหมายสไตล์ ดังนั้นฉันจึงสร้างส่วนขยาย Html Helper เพื่อวางอินพุตที่ซ่อนอยู่นอก div ที่มีช่องทำเครื่องหมาย
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());
}
ผลลัพธ์
<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">
นี่ไม่ใช่ข้อผิดพลาด! มันเพิ่มความเป็นไปได้ของการมีค่าเสมอหลังจากโพสต์แบบฟอร์มไปยังเซิร์ฟเวอร์ หากคุณต้องการที่จะจัดการกับช่องใส่ช่องทำเครื่องหมายด้วย jQuery ใช้วิธีการ prop (ผ่านคุณสมบัติ 'ตรวจสอบ' เป็นพารามิเตอร์) ตัวอย่าง:$('#id').prop('checked')
คุณสามารถลองเริ่มตัวสร้างโมเดลของคุณแบบนั้นได้:
public MemberFormModel() {
foo = true;
}
และในมุมมองของคุณ:
@html.Checkbox(...)
@html.Hidden(...)
ฉันพบสิ่งนี้ทำให้เกิดปัญหาจริง ๆ เมื่อฉันมี WebGrid ลิงก์การเรียงลำดับใน WebGrid จะเปิดขึ้นโดยการสืบค้นสองเท่าหรือ x = true & x = false เป็น x = true, false และทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์ในช่องทำเครื่องหมาย
ฉันลงเอยด้วยการใช้ jQuery เพื่อลบฟิลด์ที่ซ่อนอยู่ในฝั่งไคลเอ็นต์:
<script type="text/javascript">
$(function () {
// delete extra hidden fields created by checkboxes as the grid links mess this up by doubling the querystring parameters
$("input[type='hidden'][name='x']").remove();
});
</script>