8

Having trouble creating a list of radio buttons that are grouped together, in MVC 3 specifically, but this also applies to MVC 2.

The problem arises when radio buttons are generated using Html helpers and the model is part of an array.

Here is the cut down version of my code.

public class CollectionOfStuff {
  public MVCModel[] Things { get; set }
}

/*This model is larger and represents a Person*/    
public class MVCModel {

  [UIHint("Hidden")]
  public string Id { get; set; }

  public string Name { get; set; }

  public bool IsSelected { get; set; }
}

/*Assigned to new CollectionOfStuff property Things*/    
var items = new[] { 
 new MVCModel() { Id="0" Name = "Name here" }, new MVCModel() { Id="1" Name = "Name there" } 
}

My parent view

@model CollectionOfStuff

@for (int i = 0; i < Model.Things.Length; i++) {
    @Html.EditorFor(m => m.Things[i]);
}

My view rendering individual MVCModel objects

@Model MVCModel

    @{
      var attr = new {
        Checked = Model.IsSelected ? "checked=checked" : ""
      };
    }

    @Html.RadioButtonFor(model => model, Model.Id, attr)

Produces this output:

<input type="radio" value="0" name="MVCModel[0]" id="MVCModel_0_" data-val-required="You need to choose" data-val="true" />
<input type="radio" value="1" name="MVCModel[1]" id="MVCModel_1_" data-val-required="You need to choose" data-val="true" />

The radio buttons are not grouped, however it has the obvious advantage of writing out the meta data for validation.

The other way is by calling:

@Html.RadioButton(name: "GroupName", value: Model.Id, isChecked: Model.IsSelected)     

Produces:

<input type="radio" value="0" name="MVCModel[0].GroupName" id="MVCModel_0__GroupName">
<input type="radio" value="1" name="MVCModel[1].GroupName" id="MVCModel_1__GroupName">

Again, this doesn't produce the desired result. It's also missing the validation meta data.

Another other option is creating a custom template, but the problem with this approach is that all the meta data required for validation is not present.

Any ideas on how I can create grouped radio buttons or obtain meta data so I can create a template myself?

Razor
  • 17,271
  • 25
  • 91
  • 138

1 Answers1

14

You haven't shown how does your view model look like but you could group them by some property. So let's take an example:

public class MyViewModel
{
    [Required]
    public string SomeProperty { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

View:

@model AppName.Models.MyViewModel
@using (Html.BeginForm())
{
    <div>A: @Html.RadioButtonFor(x => x.SomeProperty, "a")</div>
    <div>B: @Html.RadioButtonFor(x => x.SomeProperty, "b")</div>
    @Html.ValidationMessageFor(x => x.SomeProperty)
    <input type="submit" value="OK" />
}

Now if you want to preselect some radio simply set the property of the view model to the corresponding value of the radio instead of writing some ugly C# code in your views:

public ActionResult Index()
{
    var model = new MyViewModel
    {
        SomeProperty = "a" // select the first radio
    };
    return View(model);
}

Obviously this technique works with any simple property type (not only strings) and with any number of radio buttons that could be associated to this property.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Darin your solution works if I hard code two radio buttons one after another like you've suggested, but this doesn't work when the template your rendering is within a loop of items. See my example, you'll see the numbers of the array create new id's that correspond to the current index. – Razor Mar 13 '11 at 22:20
  • @Vince Panuccio, then your radio buttons shouldn't be part of a collection. Simply move those properties at the root of your view model. – Darin Dimitrov Mar 13 '11 at 22:21
  • So if I have an array of Models and I want to know which one the user has selected, I can't do that? I have also added the model to my question. – Razor Mar 13 '11 at 22:33
  • @Vince Panuccio, sure you can: you define a view model in this case in which you put the property corresponding to the radio buttons and another property which corresponds to the collection you are talking about and then make your view strongly typed to this new view model. That's what view models are: they should reflect your view model logic. Or if really those radio buttons need to be part of the collection then it means that each item of this collection will get its own group of radios. Up to you to decide what you need. Both are possible. – Darin Dimitrov Mar 13 '11 at 22:35
  • 1
    @Darin Dimitrov i have exactally what you have but in my case i have multiple questions and each question has 3 radio buttons. I need to group my radio buttons at each question level. After following what you have, my radio buttons are grouped across the board. How can i fix this issue? – learning... Jul 26 '12 at 06:27
  • @learning, I don't understand what you are talking about. Please start a new thread showing your code and explaining what you are trying to achieve. – Darin Dimitrov Jul 26 '12 at 06:30
  • @one.beat.consumer, I don't know if another thread was started. Feel free to do so. – Darin Dimitrov Jul 26 '12 at 17:05
  • Sorry I don't have much time spending on chatting. So refine your question and post it on SO. If you don't have a refined question chatting won't help. I would be happy to take a look if you don't get satisfactory answer. – Darin Dimitrov Jul 26 '12 at 17:14
  • @DarinDimitrov I understand. Thank you none the less. – one.beat.consumer Jul 26 '12 at 20:15
  • @DarinDimitrov this exchange is very strange, I think its very obvious what he/she is asking. – Doug Moore Jan 08 '14 at 22:33
  • @lordscarlet, yes, it's perfectly clear what he is asking: how to group radio buttons using an HTML helper and that's precisely what my answer covers. – Darin Dimitrov Jan 08 '14 at 22:58