radiobutton net mvc labelfor example asp asp.net-mvc-3 razor

asp.net-mvc-3 - net - mvc razor radio button example



Use Html.RadioButtonFor y Html.LabelFor para el mismo Modelo pero diferentes valores (7)

Tengo esta Plantilla Razor

<table> <tr> <td>@Html.RadioButtonFor(i => i.Value, "1")</td> <td>@Html.LabelFor(i => i.Value, "true")</td> </tr> <tr> <td>@Html.RadioButtonFor(i => i.Value, "0")</td> <td>@Html.LabelFor(i => i.Value, "false")</td> </tr> </table>

Eso me da este HTML

<table> <tr> <td><input id="Items_1__Value" name="Items[1].Value" type="radio" value="1" /></td> <td><label for="Items_1__Value">true</label></td> </tr> <tr> <td><input checked="checked" id="Items_1__Value" name="Items[1].Value" type="radio" value="0" /></td> <td><label for="Items_1__Value">false</label></td> </tr> </table>

Así que tengo ID Items_1__Value dos veces, lo cual, por supuesto, no es bueno y no funciona en un navegador cuando hago clic en la segunda etiqueta "falso", se activará la primera radio.

Sé que podría agregar un Id propio en RadioButtonFor y referirme a eso con mi etiqueta, pero eso no es muy bueno, ¿o sí? Especialmente porque estoy en un bucle y no puedo simplemente usar el nombre "valor" con un número agregado, que también terminaría en múltiples Id. De Dom en mi marcado HTML final.

No debería ser una buena solución para esto?


@Scott Rippey casi lo tiene, pero supongo que debe estar usando una versión diferente de MVC3 porque para mí @Html.LabelFor no tiene sobrecargas que tomarán 3 argumentos. Descubrí que usar el @Html.Label normal funciona bien:

@{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioButton_True");} @Html.Label(id, "True:") @Html.RadioButtonFor(m => m.radioButton, true, new { id }) @{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioButton_False");} @Html.Label(id, "False:") @Html.RadioButtonFor(m => m.radioButton, false, new { id })

esto le permite hacer clic en la etiqueta y seleccionar el botón de radio asociado como era de esperar.


Aparentemente hay una buena solución

<td>@Html.RadioButtonFor(i => i.Value, true)</td> <td>@Html.RadioButtonFor(i => i.Value, false)</td>


Aquí hay un HtmlHelper que puede usar, aunque puede hacerlo para personalizarlo. Solo apenas probado, entonces YMMV.

public static MvcHtmlString RadioButtonWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes = null) { var name = ExpressionHelper.GetExpressionText(expression); var id = helper.ViewData.TemplateInfo.GetFullHtmlFieldId(name + "_" + value); var viewData = new ViewDataDictionary(helper.ViewData) {{"id", id}}; if (htmlAttributes != null) { var viewDataDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); foreach (var keyValuePair in viewDataDictionary) { viewData[keyValuePair.Key] = keyValuePair.Value; } } var radioButton = helper.RadioButtonFor(expression, value, viewData); var tagBuilder = new TagBuilder("label"); tagBuilder.MergeAttribute("for", id); tagBuilder.InnerHtml = value.ToString(); return new MvcHtmlString(radioButton.ToHtmlString() + tagBuilder.ToString()); }


Me he estado preguntando cómo MVC determina los nombres de campo y las identidades "anidados". Tomó un poco de investigación en el código fuente de MVC para averiguarlo, pero creo que tengo una buena solución para ti.

Cómo EditorTemplates y DisplayTemplates determinan nombres de campo e ID

Con la introducción de EditorTemplates y DisplayTemplates, el marco MVC agregó ViewData.TemplateInfo que contiene, entre otras cosas, el "prefijo de campo" actual, como "Items[1]." . Las plantillas anidadas usan esto para crear nombres e ID únicos.

Cree nuestros propios ID únicos:

La clase TemplateInfo contiene un método interesante, GetFullHtmlFieldId . Podemos usar esto para crear nuestros propios ID únicos así:

@{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("fieldName");} @* This will result in something like "Items_1__fieldName" *@

Por la victoria

A continuación, le mostramos cómo lograr el comportamiento correcto para su ejemplo:

<table> <tr> @{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioTrue");} <td>@Html.RadioButtonFor(i => i.Value, "1", new{id})</td> <td>@Html.LabelFor(i => i.Value, "true", new{@for=id})</td> </tr> <tr> @{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioFalse");} <td>@Html.RadioButtonFor(i => i.Value, "0", new{id})</td> <td>@Html.LabelFor(i => i.Value, "false", new{@for=id})</td> </tr> </table>

Que le dará el siguiente HTML:

<table> <tr> <td><input id="Items_1__radioTrue" name="Items[1].Value" type="radio" value="1" /></td> <td><label for="Items_1__radioTrue">true</label></td> </tr> <tr> <td><input checked="checked" id="Items_1__radioFalse" name="Items[1].Value" type="radio" value="0" /></td> <td><label for="Items_1__radioFalse">false</label></td> </tr> </table>

Renuncia

La sintaxis de My Razor está poco desarrollada, por lo tanto, avíseme si este código tiene errores de sintaxis.

Por lo que vale

Es bastante desafortunado que esta funcionalidad no esté incorporada en RadioButtonFor . Parece lógico que todos los botones de radio prestados tengan una ID que sea una combinación de su name Y value , pero ese no es el caso, tal vez porque eso sería diferente de todos los demás ayudantes de HTML.
La creación de sus propios métodos de extensión para esta funcionalidad también parece una opción lógica. Sin embargo, podría ser complicado usar la "sintaxis de expresión" ... así que recomendaría sobrecargar .RadioButton(name, value, ...) lugar de RadioButtonFor(expression, ...) . Y es posible que desee una sobrecarga para .Label(name, value) también.
Espero que todo tenga sentido, porque hay mucho "completar los espacios en blanco" en ese párrafo.


No es perfecto, pero funciona bien,

<table> <tr> <td>@ReplaceName(Html.RadioButtonFor(i => i.Value, "1"))</td> <td>@Html.LabelFor(i => i.Value[0], "true")</td> </tr> <tr> <td>@ReplaceName(Html.RadioButtonFor(i => i.Value, "0"))</td> <td>@Html.LabelFor(i => i.Value[1], "false")</td> </tr> </table> @functions { int counter = 0; MvcHtmlString ReplaceName(MvcHtmlString html){ return MvcHtmlString.Create(html.ToString().Replace("__Value", "__Value_" + counter++ +"_")); } }


No sobreinyecte una solución para esto. Todo lo que intenta lograr es hacer que los botones de radio respondan a los clics en el texto. Manténgalo simple y simplemente envuelva sus botones de radio en etiquetas de etiqueta:

<table> <tr> <td><label>@Html.RadioButtonFor(i => i.Value, "1")True</label></td> </tr> <tr> <td><label>@Html.RadioButtonFor(i => i.Value, "0")False</label></td> </tr> </table>

El asistente de LabelFor html generalmente se usa para traer el Nombre del atributo de Visualización en su Modelo de Vista (por ejemplo, "[Mostrar (Nombre =" Escriba su nombre ")]).

Con los botones de opción, el nombre no es particularmente útil, porque tiene una línea de texto diferente para cada botón de opción, lo que significa que está bloqueado al codificar el texto en su vista de todos modos.


Puedes agregar texto con etiquetas

<td>@Html.RadioButtonFor(i => i.Value, true) <text>True</text></td> <td>@Html.RadioButtonFor(i => i.Value, false) <text>False</text></td>