Właśnie zauważyłem, że Html.CheckBox("foo")
generuje 2 wejścia zamiast jednego, ktoś wie dlaczego tak jest?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Właśnie zauważyłem, że Html.CheckBox("foo")
generuje 2 wejścia zamiast jednego, ktoś wie dlaczego tak jest?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Odpowiedzi:
Jeśli pole wyboru nie jest zaznaczone, pole formularza nie jest przesyłane. Dlatego w ukrytym polu zawsze występuje fałszywa wartość. Jeśli pozostawisz pole wyboru niezaznaczone, formularz nadal będzie miał wartość z ukrytego pola. W ten sposób ASP.NET MVC obsługuje wartości pól wyboru.
Jeśli chcesz to potwierdzić, zaznacz pole wyboru w formularzu nie za pomocą Html.Hidden, ale za pomocą <input type="checkbox" name="MyTestCheckboxValue"></input>
. Pozostaw niezaznaczone pole wyboru, prześlij formularz i sprawdź wartości żądań po stronie serwera. Zobaczysz, że nie ma wartości pola wyboru. Gdybyś miał ukryte pole, zawierałoby ono MyTestCheckboxValue
wpis z false
wartością.
IsActive
, która jest inicjowana true
w konstruktorze. Użytkownik usuwa zaznaczenie pola wyboru, ale ponieważ wartość nie jest wysyłana do serwera, model spoiwa nie odbiera jej, a wartość właściwości nie jest zmieniana. Model segregatorowy nie powinien zakładać, że jeśli wartość nie zostanie wysłana, zostanie ustawiona wartość false, ponieważ może to być Twoja decyzja o nieprzesyłaniu tej wartości.
false
wartość, nawet jeśli są zaznaczone, i to jest mylące. Wyłączone pola wyboru nie powinny w ogóle wysyłać żadnej wartości, jeśli ASP.NET chce być zgodny z domyślnym zachowaniem HTTP.
Możesz napisać pomocnika, aby zapobiec dodawaniu ukrytych danych wejściowych:
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);
}
}
Użyj tego:
@Html.CheckBoxSimple("foo", new {value = bar.Id})
@using Your.Name.Space
na górze pliku .cshtml razor.
System.Web.Mvc.Html
aby był dostępny we wszystkich widokach
po zaznaczeniu i przesłaniu pola wyboru wykonaj to
if ($('[name="foo"]:checked').length > 0)
$('[name="foo"]:hidden').val(true);
Podejście ręczne jest następujące:
bool IsDefault = (Request.Form["IsDefault"] != "false");
To mocno typowana wersja rozwiązania Aleksandra Trofimowa:
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);
}
}
Ukryte dane wejściowe powodowały problemy ze stylowymi polami wyboru. Więc stworzyłem rozszerzenie pomocnika HTML, aby umieścić ukryte dane wejściowe poza div zawierającym 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());
}
Wynik
<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">
Możesz spróbować zainicjować konstruktor swojego modelu w następujący sposób:
public MemberFormModel() {
foo = true;
}
i twoim zdaniem:
@html.Checkbox(...)
@html.Hidden(...)
Odkryłem, że to naprawdę spowodowało problemy, gdy miałem WebGrid. Łącza sortujące w sieci Web zamieniłyby się przez podwojone kwerendy lub x = true i x = false na x = true, false i spowodowałyby błąd analizy w polu wyboru dla.
Skończyło się na użyciu jQuery do usunięcia ukrytych pól po stronie klienta:
<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>