Используйте Html.RadioButtonFor и Html.LabelFor для одной и той же модели, но с разными значениями. - PullRequest
32 голосов
/ 30 ноября 2011

У меня есть этот шаблон бритвы

<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>

Это дает мне этот 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>

Таким образом, у меня есть идентификатор Items_1__Value дважды, что, конечно, не очень хорошо и не работает в браузере, когда я нажимаю на второй ярлык «ложь», первое радио будет активировано.

Я знаю, что мог бы добавить собственный идентификатор в RadioButtonFor и сослаться на это со своим лейблом, но это не очень хорошо, не так ли? Тем более, что я нахожусь в цикле и не могу просто использовать имя «значение» с добавленным номером, это также может оказаться в нескольких идентификаторах Dom в моей окончательной разметке HTML.

Не должно ли быть хорошее решение для этого?

Ответы [ 7 ]

58 голосов
/ 01 января 2014

Не переборщи решение для этого. Все, что вы пытаетесь сделать, это чтобы переключатели реагировали на нажатия на текст. Сохраняйте это простым и просто оберните ваши радио-кнопки в теги меток:

<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>

Помощник LabelFor html обычно используется для ввода атрибута «Имя из дисплея» в вашей модели представления (например, «[Display (Name =« Введите ваше имя »)]).

С радио-кнопками название не особенно полезно, потому что у вас есть разные строки текста для каждой радио-кнопки, что означает, что вы застряли в коде текста в любом случае.

47 голосов
/ 24 декабря 2011

Мне было интересно, как MVC определяет «вложенные» имена полей и идентификаторы.Потребовалось немного изучить исходный код MVC, чтобы выяснить это, но я думаю, что у меня есть хорошее решение для вас.

Как EditorTemplates и DisplayTemplates определяют имена и идентификаторы полей

С введениемВ EditorTemplates и DisplayTemplates в инфраструктуру MVC добавлена ​​ViewData.TemplateInfo, которая содержит, помимо прочего, текущий «префикс поля», например "Items[1].".Вложенные шаблоны используют это для создания уникальных имен и идентификаторов.

Создайте наши собственные уникальные идентификаторы:

Класс TemplateInfo содержит интересный метод, GetFullHtmlFieldId.Мы можем использовать это для создания наших собственных уникальных идентификаторов, например:

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

Для выигрыша

Вот как добиться правильного поведения для вашего примера:

<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>

Что даст вам следующий 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>

Отказ от ответственности

Синтаксис моего Razor недостаточно развит, поэтому, пожалуйста, дайте мне знать, если этот код имеет синтаксические ошибки.

Длясколько стоит

Очень жаль, что эта функция не встроена в RadioButtonFor.Кажется логичным, что все визуализированные радиокнопки должны иметь идентификатор, который является комбинацией его name И value, но это не так - возможно, потому что это будет отличаться от всех других помощников HTML.
Создание вашегособственные методы расширения для этой функциональности тоже кажутся логичным выбором.Тем не менее, может быть сложно использовать «синтаксис выражения» ... поэтому я бы рекомендовал перегрузить .RadioButton(name, value, ...) вместо RadioButtonFor(expression, ...).И вам может потребоваться перегрузка и для .Label(name, value).
Я надеюсь, что все это имело смысл, потому что в этом абзаце много "пробелов".

8 голосов
/ 18 июля 2012

@ Скотт Риппи почти что имеет, но я думаю, он использует другую версию MVC3 для меня, потому что для меня @Html.LabelFor не имеет перегрузок, которые будут принимать 3 аргумента.Я обнаружил, что использование обычного @Html.Label прекрасно работает:

@{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 })

. Это позволяет вам щелкнуть ярлык и выбрать соответствующую кнопку радио, как вы ожидаете.

1 голос
/ 24 декабря 2011

Не идеально, но работает, хотя,

<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++ +"_"));
    }
}
0 голосов
/ 09 октября 2015

Вы можете добавить текст с тегами

<td>@Html.RadioButtonFor(i => i.Value, true) <text>True</text></td>
<td>@Html.RadioButtonFor(i => i.Value, false) <text>False</text></td>
0 голосов
/ 04 сентября 2015

Вот HtmlHelper, который вы можете использовать, хотя вы можете настроить его. Только еле проверено, так что 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());
    }
0 голосов
/ 30 ноября 2011

Видимо, есть хорошее решение

    <td>@Html.RadioButtonFor(i => i.Value, true)</td>
    <td>@Html.RadioButtonFor(i => i.Value, false)</td>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...