Я щойно помітив, що 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
в конструктор. Користувач знімає прапорець, але оскільки значення не надсилається серверу, палітурка моделі не приймає його, а значення властивості не змінюється. В’яжуча модель не повинна вважати, що якщо значення не надсилається, воно було встановлено на помилкове значення, оскільки це може бути ваше рішення не надсилати це значення.
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");
Це сильно типізована версія рішення Олександра Трофімова:
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);
}
}
Прихований вклад викликав проблеми зі стильовими прапорцями. Тому я створив Html Helper Extension, щоб розмістити прихований вхід поза ділом, що містить 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());
}
Результат
<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">
Ви можете спробувати ініціалізувати конструктор своєї моделі так:
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>