Posts
208
Comments
1144
Trackbacks
51
MVC RadioButtonList HTML Helper – Take 3

In two previous posts, I talked about ways to create your own HTML Helper to generate a radio button list.  In the first post I leveraged the FluentHtml library to create a table layout.  In the second post I switched this to using a div instead of a table.  The crux of the issue was that I wanted to make sure the the “id” and “name” attributes were set correctly and MVC out of the box doesn’t seem to do this properly.  Recently I discovered a way to successfully do this without “wrapping” the FluentHtml library but by using it directly while leveraging a “RadioSet” like this:

   1:  <%=this.RadioSet(m => m.Name).Options(Model.FooBarList) %>

To produce HTML that looks like this:

   1:  <div id="Name">
   2:      <input id="Name_Foo" name="Name" type="radio" value="Foo" /><label for="Name_Foo" id="Name_Foo_Label">Foo</label>
   3:      <input id="Name_Bar" name="Name" type="radio" value="Bar" /><label for="Name_Bar" id="Name_Bar_Label">Bar</label>
   4:  </div>

which is exactly what I want.  However, there are a couple of gotchas I ran into for making this work properly.  First off, it’s important to note that the Options() method above is taking an IEnumerable<SelectListItem> and FooBarList is IEnumerable<SelectListItem>.  The first thing I tried was creating my list like this:

   1:  private static IEnumerable<SelectListItem> CreateFooBarList()
   2:  {
   3:      var list = new List<string> { "Foo", "Bar" };
   4:      return new SelectList(list);
   5:  }

This resulted in HTML that was broken as the id’s and value’s were not set correctly:

   1:  <div id="Name">
   2:      <input id="Name" name="Name" type="radio" value="" /><label for="Name" id="Name_Label">Foo</label>
   3:      <input id="Name" name="Name" type="radio" value="" /><label for="Name" id="Name_Label">Bar</label>
   4:  </div>

So realized it was probably because that SelectListItem constructor just didn’t assign the Value property when a list of strings was sent in.  So I changed to this:

   1:  private static IEnumerable<SelectListItem> CreateFooBarList()
   2:  {
   3:      var list = new List<SelectListItem>
   4:      {
   5:          new SelectListItem { Text = "Foo", Value = "Foo" },
   6:          new SelectListItem { Text = "Bar", Value = "Bar" }
   7:      };
   8:      return new SelectList(list);
   9:  }

I figured now that I was using an actual strongly-typed SelectList I would be all set.  But unfortunately, the rendered HTML was even worse now:

   1:  <div id="Name">
   2:      <input id="Name" name="Name" type="radio" value="" /><label for="Name" id="Name_Label">System.Web.Mvc.SelectListItem</label>
   3:      <input id="Name" name="Name" type="radio" value="" /><label for="Name" id="Name_Label">System.Web.Mvc.SelectListItem</label>
   4:  </div>

It turns out that the way I had to fix this was to specify *all* arguments on the SelectList constructor with the dataTextField and dataValueField as shown on line #8 below:

   1:  private static IEnumerable<SelectListItem> CreateFooBarList()
   2:  {
   3:      var list = new List<SelectListItem>
   4:      {
   5:          new SelectListItem { Text = "Foo", Value = "Foo" },
   6:          new SelectListItem { Text = "Bar", Value = "Bar" }
   7:      };
   8:      return new SelectList(list, "Value", "Text");
   9:  }

Now the HTML and all attributes are correct.  You would *think* that the constructor of the SelectList would be smart enough to identify that the IEnumerable collection that was sent in was of type IEnumerable<SelectListItem> (which is what it ultimately wants) and set those arguments for you automatically. But it looks like that was a naive assumption on my part.  Easy enough to add a simple extension method to do this for you throughout your codebase. Make sure to watch out for this in your own code – I won’t make this mistake again.

posted on Friday, August 7, 2009 3:33 AM Print
Comments
Gravatar
# re: MVC RadioButtonList HTML Helper – Take 3
beginner
11/12/2009 8:12 AM
Could you please post the complete code for this helper and how it's supposed to be called?
Gravatar
# re: MVC RadioButtonList HTML Helper – Take 3
Steve
11/12/2009 11:23 AM
@beginner - I'm not following your question. The complete code including how it's supposed to be called is the first line of code posted:

<%=this.RadioSet(m => m.Name).Options(Model.FooBarList) %>

That's it. Just call the RadioSet() helper in the FluentHtml library. The one catch is that - for whatever collection you're using - you need to correctly set the constructor for the SelectList like I did on line #8 of the last code sample.
Gravatar
# re: MVC RadioButtonList HTML Helper – Take 3
losingrose
12/24/2009 3:52 AM
the bug is label for="Name"
this bind in order to case the label don't match the right raido with id attribute

Post Comment

Title *
Name *
Email
Comment *  
Verification

View Steve Michelotti's profile on LinkedIn

profile for Steve Michelotti at Stack Overflow, Q&A for professional and enthusiast programmers




Google My Blog

Tag Cloud