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?

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

11 Comments

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.
@Vince Panuccio, then your radio buttons shouldn't be part of a collection. Simply move those properties at the root of your view model.
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.
@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 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?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.