Ho appena notato che Html.CheckBox("foo")
genera 2 input invece di uno, qualcuno sa perché è così?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Ho appena notato che Html.CheckBox("foo")
genera 2 input invece di uno, qualcuno sa perché è così?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Risposte:
Se la casella di controllo non è selezionata, il campo modulo non viene inviato. Ecco perché c'è sempre un valore falso nel campo nascosto. Se si lascia deselezionata la casella di controllo, il modulo avrà comunque valore dal campo nascosto. Ecco come ASP.NET MVC gestisce i valori della casella di controllo.
Se vuoi confermarlo, posiziona una casella nel modulo non con Html. Nascosto, ma con <input type="checkbox" name="MyTestCheckboxValue"></input>
. Lascia la casella deselezionata, invia il modulo e controlla i valori delle richieste pubblicate sul lato server. Vedrai che non esiste un valore per la casella di controllo. Se avessi un campo nascosto, conterrebbe la MyTestCheckboxValue
voce con false
valore.
IsActive
, che viene avviata true
nel costruttore. L'utente deseleziona la casella di controllo, ma poiché il valore non viene inviato al server, il raccoglitore modello non lo raccoglie e il valore della proprietà non viene modificato. Il raccoglitore modello non dovrebbe presumere che, se il valore non viene inviato, è stato impostato su false, poiché potrebbe essere la decisione di non inviare questo valore.
false
valore anche se sono selezionate e questo è confuso. Le caselle di controllo disabilitate non devono inviare alcun valore se ASP.NET desidera essere compatibile con il comportamento HTTP predefinito.
Puoi scrivere un aiuto per evitare di aggiungere l'input nascosto:
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);
}
}
usalo:
@Html.CheckBoxSimple("foo", new {value = bar.Id})
@using Your.Name.Space
all'inizio del file di visualizzazione del rasoio .cshtml.
System.Web.Mvc.Html
per essere accessibile in tutte le viste
quando la casella di controllo è selezionata e inviata, eseguire ciò
if ($('[name="foo"]:checked').length > 0)
$('[name="foo"]:hidden').val(true);
L'approccio manuale è questo:
bool IsDefault = (Request.Form["IsDefault"] != "false");
Questa è la versione fortemente tipizzata della soluzione di 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);
}
}
L'input nascosto stava causando problemi con le caselle di controllo con stile. Così ho creato un'estensione Helper HTML per posizionare l'input nascosto all'esterno del div contenente il 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());
}
Risultato
<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">
Questo non è un bug! Aggiunge la possibilità di avere sempre un valore, dopo aver pubblicato il modulo sul server. Se si desidera gestire i campi di input della casella di controllo con jQuery, utilizzare il metodo prop (passare la proprietà 'checked' come parametro). Esempio:$('#id').prop('checked')
Puoi provare a inizializzare il costruttore del tuo Modello in questo modo:
public MemberFormModel() {
foo = true;
}
e a tuo avviso:
@html.Checkbox(...)
@html.Hidden(...)
Ho scoperto che questo ha causato problemi quando avevo un WebGrid. I collegamenti di ordinamento su WebGrid si trasformerebbero per il querystring raddoppiato o x = true & x = false in x = true, false e causerebbero un errore di analisi nella casella di controllo per.
Ho finito con jQuery per eliminare i campi nascosti sul lato client:
<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>