Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Radio Button List for MVC 4

2.00/5 (1 vote)
23 Sep 2013CPOL2 min read 58.2K  
Helper for RadioList in MVC 4

Introduction

If you are familier (or learning) MVC 4, you will notice that the name of each control is generated by the MVC framework (be it Razor or Asp.Net view engine). These names are in certain formal (e.g. ParentObjectName_PropertyName) so that while posting back the form the values in the html controls are bound back to the model's (or view model's) respective properties.

This works absolutely fine with all controls except when you desire to have a radio button list, typicaly for a radio list the "name" property is same for all the radio buttons in a certain list.

The problem comes when the form is posted back, the correct value won't get mapped to the respective model (which is mapped to the radio button). Esp when you want to pass all the options/controls (whether it is selected or not, e.g. selecting a preferred address among multiple addresses entered by the user in UI ) 

Background  

I have searched many blogs but didn't find a generic solution for radio lists. All were addressing specific problems. 

Using the code

This utility needs to know what is the parent div element, under which these radio buttons reside. 

Let me give you a step by step of creating this utility 

1. Custom HTML Helper 

    Make a custom HTML helper (a static class) to make your custom HTML helper 

C#
/// <summary>
    /// Custom HTML helper for radio button list
    /// </summary>
    public static class RadioButtonListHelper
    {
 	/// <summary>
        /// RadioButtons the list for.
        /// </summary>
        /// <typeparam name="TModel">The type of the model.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <param name="htmlHelper">The HTML helper.</param>
        /// <param name="expression">The expression.</param>
        /// <param name="value">The value.</param>
        /// <param name="parentContainer">The parent container.</param>
        /// <returns>Custom MvcHtmlString with radio list functionality with jquery.mvc.radiolist.js included in the view</returns>
        public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, string parentContainer)
        {
            RouteValueDictionary htmlAttrs = new RouteValueDictionary();
            htmlAttrs.Add("radio-list", "true");
            htmlAttrs.Add("radio-list-parent", parentContainer);
            return htmlHelper.RadioButtonFor(expression, value, htmlAttrs);
        }


    }<span style="font-size: 9pt;"</span>

 You can also have another overload accepting html attributes from your view :-

C#
        /// <summary>
        /// RadioButtons the list for.
        /// </summary>
        /// <typeparam name="TModel">The type of the model.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <param name="htmlHelper">The HTML helper.</param>
        /// <param name="expression">The expression.</param>
        /// <param name="value">The value.</param>
        /// <param name="htmlAttributes">The HTML attributes.</param>
        /// <param name="parentContainer">The parent container.</param>
        /// <returns>Custom MvcHtmlString with radio list functionality with jquery.mvc.radiolist.js included in the view</returns>
        public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes, string parentContainer)
        {
            var htmlAttrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            htmlAttrs.Add("radio-list", "true");
            htmlAttrs.Add("radio-list-parent", parentContainer);
            return htmlHelper.RadioButtonFor(expression, value, htmlAttrs);
        } 

 

This will add two custom html attributes to the radio button html rendered. 

i) "radio-list" - This will be used by a custom js file (which I will explain later)

ii) "radio-list-parent" - This will contain the parent div name (which will be used in your view and the custom js file)

2. Custom Js file 

 jquery.mvc.radiolist.js -   This will make sure  that when you check a certain radio button in the MainDiv area all other radio buttons are unchecked. 

JavaScript
$(document).ready(function () {
    $(":radio[radio-list='true']").each(function () {
        var mainDiv = $("#" + this.id).attr("radio-list-parent");
        var element = $("#" + this.id)[0];
        $("#" + this.id).click(function () {
            if ($("#" + mainDiv).find(":radio")) {
                if ($("#" + element.id).prop("checked")) {
                    $("#" + element.id).prop("value", "true");
                    $("#" + mainDiv).find(":radio").each(function () {
                        if (this.id != element.id) {
                            $("#" + this.id).prop("checked", false);
                            $("#" + this.id).prop("value", "false")
                        }
                    });
                }
            }
        });
    });
}); 

3. Changes in View:-

  I am showing it in a view/partial view where there is a loop (i.e. it is a repeating control/view). But this utility can be used anywhere, you just need to make sure that these radio buttons are surrounded with a div. I have shown it in razor view engine but in the same way you can use it in ASP.NET views:-

[PS: make sure you put a using block for the namespace where you have written your custom html helper (RadioButtonListHelper), small thing but worth noting down :) ] 

C#
<div id="divMain"> 
@for (int counter = 0; counter < Model.Count; counter++)
        {
		@Html.RadioButtonListFor(model => model[counter].IsPreferred, "false", "divMain")
		//Rest of the controls
	}
</div> 

You can also add your custom html attributes before passing the parent div (as shown in the overload above). This will make sure all your radio buttons map back to their respective model properties once posted. 

In above case the data type for IsPreferred as nullable bool (i.e. bool?)  

I will post updates if I add some more overloads to this. 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)