An MVC 3 example which uses the Radio Button helper twice on a page to create 3 radio buttons with the first radio button helper and 2 radio buttons with the 2nd helper. Both have validation to ensure 1 option is selected. And if the form fails validation the chosen radio option is preselected when the form is reshown.
The radio buttons can be shown on the page horizontally or vertically.
The Html Helper Method
Essentially all this helper does is loop round a list that you provide it and for each item in the list creates a html radio button and a label for it.
I created a new class with the following code:
using System; namespace MVC3_RadioButtonList_Helper_Sample if (listOfValues != null) // Create and populate a radio button using the existing html helpers // Create the html string that will be returned to the client return MvcHtmlString.Create(sb.ToString()); |
I’ve added a div around the radio button and it’s label with a class of ‘RadioButton’, this will let you in CSS position the radio button either vertically or horizontally. The default is vertically:
But you can switch this to horizontal with a bit of CSS
.RadioButton { float:left; } |
The rest of this article shows how to use the RadioButtonForSelectList helper, you reference it in a view like this: @Html.RadioButtonForSelectList(m => m.TestRadio, Model.TestRadioList)
The Model
For this example I just created an empty MVC3 application and added this model.
using System; namespace MVC3_RadioButtonList_Helper_Sample.Models [Required(ErrorMessage = "You must select an option for TestRadio")] [Required(ErrorMessage = "You must select an option for TestRadio2")] public class aTest |
The Controller Action
I added the following to my controller to populate the model with 2 different lists one for each of the radio button helpers. The first radio button help also has a default value set so the middle option (‘Line2’) will be pre-selected.
I also changed the Index HttpPost method so that if validation fails the same list of radio buttons is added to the model (obviously I have duplicated the list creation code, in a live example you should create a common function).
using System; namespace MVC3_RadioButtonList_Helper_Sample.Controllers List<aTest> list2 = new List<aTest>(); var model = new IndexViewModel(); return View(model); [HttpPost] // If we got this far, something failed, redisplay form List<aTest> list2 = new List<aTest>(); model.TestRadioList = sl; return View(model); |
The View
To test the html helper I added a view that is bound to the IndexViewModel.
I added a using statement so the helper method would be found by intelisence @using MVC3_RadioButtonList_Helper_Sample
I added the new helper RadioButtonForSelectList and passed in the TestRadio property from the IndexViewModel which is where the selected result will be put (the radio button ID value e.g. 2).
And the TestRadioList which is a list of SelectListItems for which a radio button will be created for each item in the list.
@Html.RadioButtonForSelectList(m => m.TestRadio, Model.TestRadioList) @Html.ValidationMessageFor(m => m.TestRadio) |
So the error message (as specified in the model ‘TestRadio’ property is shown when no radio button is selected I added a validation message helper.
I then added a 2nd radio button helper to the form like this, which is bound to a different list and it’s return value will be in TestRadio2.
@Html.RadioButtonForSelectList(m => m.TestRadio2, Model.TestRadioList2) |
The form below shows the validation in action:
Here is the source code.
Thanks for the comments I've updated the post above to reflect these. The helper class now:
ReplyDelete- Adds a css class to allow you to position the radio buttons horizontally or vertically.
- The example shows how to set a default value.
- There is no problem with having more than one radio button helper on a page so I've updated the post to show how to do this.
- Source code is now available to download.
Thanks for useful article, I also need to know how you can read the values when a user select an item?
ReplyDelete(Amir)
Thank you for a very useful post and helper.
ReplyDeleteHow can I make the list of TestRadioList and TestRadio inside IndexViewModel dynamic? I tried the whle code using List and defining only 1 TestRadioList and TestRadio within IndexViewMode. But then all the radio button select lists had the same name, and so unique selection per TsxtRadioList couldn't happen.
Very useful!! I converted to VB.NET and then added an optional GroupName parameter on the helper class so I could "name" the id myself.
ReplyDeleteThis way, I can use jQuery to attach a client side handler for clicking on any radio button.
nice work....
ReplyDeleteVery helpful, thanks. Would it be possible to write one for a CheckBoxForSelectList?
ReplyDeleteThanks,
Hi Jon,
ReplyDeleteI tried to use your helper, but I've got following error
"
Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'RadioButtonForSelectList' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
"
Could you please give me any idea, why I've got that error?
Thanks,
Aleks
@Anonymous - it sounds like one of the things you're trying to pass into it is a dynamic type (such as any property off of ViewBag). You need to explicitly cast it to string (or int or whatever).
ReplyDeleteThanks for a very useful article. I modified it for Enums and it has been great.
ReplyDeleteHi, why did you defined List list and list 2 two times (in Index GET and POST)?
ReplyDeleteIsn't enough to define in Index GET ?
Can't Express my words.. tat much your article helped me man.. Great job.. keep it up.. Fantastic.. post..!! I really appreciate..!
ReplyDeleteReally very useful article. thanks so much...
ReplyDeleteThanks, It 's Perfect article, Thank you Jon
ReplyDeleteThanks Jon but this groups all radio buttons with the same name when I use more than one RadioButtonForSelectList in a foreach loop like so:
ReplyDeleteforeach (Question question in Model.Questions) {
<p>@question.question_text</p>
@Html.RadioButtonForSelectList(m => question.SelectedResponse, question.ResponseOptions)
}
Thanks Jon!
ReplyDeleteI used this metod in my projects and all was ok.
But now it is nessary for me show 60 (or more) radiogroups on one page.
Did you now, how can I use array of properties innstead of 60 properties?
Thanks Jon. This worked for me. Is there a way to set a default selected radiobutton?
ReplyDeleteI figured it out. I added an optional argument String selectedItemValue = "" and then
ReplyDeleteobject htmlAttrib = new { id = id };
if (selectedItemValue == item.Value) htmlAttrib = new { id = id, @checked = "checked" };
// Create and populate a radio button using the existing html helpers
var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
var radio = htmlHelper.RadioButtonFor(expression, item.Value, htmlAttrib).ToHtmlString();
Thanks Jon! Very useful article!
ReplyDeleteThanks Jon! Useful article!
ReplyDelete