MVC Radiobutton binding complex object
Asked Answered
G

1

6

I have MVC3 web application where we need to populate radio button list with validation. My Model is something like this:

public class EmployeesViewModel
{
     public List<Employee> listEmployee { get; set; } //To persist during post
     public IEnumerable<SelectListItem> selectListEmployee { get; set; }

     [Required]
     public Employee selectedEmployee { get; set; }
}

public class Employee
{
  public int ID {get; set;}
  public string Name {get; set}
  public string Department {get; set}
 }

I need to populate radiobutton list something like below:

  • Employee1ID - Employee1Name - Employee1Department // id - name - department
  • Employee2ID - Employee2Name - Employee2Department
  • Employee3ID - Employee3Name - Employee3Department

Selected Employee should be stored into "selectedEmployee" field. What is the best or clean way to populate these radio button List in MVC3?

Note: Mainly Looking for two task: 1. storing "Employee" object in each "Input" radio button tag, so that selected employee will be saved to "selectedEmployee" field 2. Best way to mark "Employee" object as required field

Much appreciate your help!

Thanks,

Gynecologist answered 10/7, 2011 at 3:20 Comment(0)
B
12

Here's what I would recommend you. Start with a clean view model, one that really expresses what the view contains as information:

public class EmployeesViewModel
{
    public List<EmployeeViewModel> ListEmployee { get; set; }

    [Required]
    public int? SelectedEmployeeId { get; set; }
}

public class EmployeeViewModel
{
    public int ID { get; set; }
    public string Label { get; set; }
}

then a controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new EmployeesViewModel
        {
            ListEmployee = GetEmployees()
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(EmployeesViewModel model)
    {
        if (!ModelState.IsValid)
        {
            // the model is invalid, the user didn't select an employee
            // => refetch the employee list from the repository and
            // redisplay the view so that he can fix the errors
            model.ListEmployee = GetEmployees();
            return View(model);
        }

        // validation passed at this stage
        // TODO: model.SelectedEmployeeId will contain the id
        // of the selected employee => use your repository to fetch the
        // actual employee object and do something with it 
        // (like grant him the employee of the month prize :-))

        return Content("thanks for submitting", "text/plain");
    }

    // TODO: This doesn't belong here obviously
    // it's only for demonstration purposes. In the real 
    // application you have a repository, use DI, ...
    private List<EmployeeViewModel> GetEmployees()
    {
        return new[]
        {
            new EmployeeViewModel { ID = 1, Label = "John (HR)" },
            new EmployeeViewModel { ID = 2, Label = "Peter (IT)" },
            new EmployeeViewModel { ID = 3, Label = "Nathalie (Sales)" },
        }.ToList();
    }
}

and finally a view:

@model EmployeesViewModel

@using (Html.BeginForm())
{
    @Html.ValidationMessageFor(x => x.SelectedEmployeeId)
    @foreach (var employee in Model.ListEmployee)
    {
        <div>
            @Html.RadioButtonFor(x => x.SelectedEmployeeId, employee.ID, new { id = "emp" + employee.ID })
            @Html.Label("emp" + employee.ID, employee.Label)
        </div>
    }
    <input type="submit" value="OK" />
}
Barbarous answered 10/7, 2011 at 8:57 Comment(3)
Thanks Darin! that view model really serve the purpose!Gynecologist
Looking for one more thought from you. Lets say in my case what if I have composite key in my "Employee" table? (like "ID" and "Department" together form composite key) In this case I need to pass ID and Department to get the real object I want. What is the best way to do that?Gynecologist
@matmat, a radio button sends only a single value, so having composite keys in this case wouldn't make sense. You could use a unique primary key of your database. As an alternative you could have the ID property be a string of the form ID_DEPT which you could split in your controller when the form is posted back and fetch the two values but that seems hackish. A unique primary key is a much better approach.Barbarous

© 2022 - 2024 — McMap. All rights reserved.