Bv202
Bv202

Reputation: 4044

Checkboxes - how to implement?

I have a viewmodel which contains an Episode and a boolean "watched":

public class WatchedEpisodeViewModel
{
    public Episode Episode { get; set; }
    public bool Watched { get; set; }
}

I have a list of these bound to my view:

@model IEnumerable<Seriebeheer.Web.Models.WatchedEpisodeViewModel>

I'm listing this information:

         @foreach (var episode in Model)
         {
             <tr>
                 <td>@episode.Episode.ID</td>
                 <td>@episode.Episode.Name</td>
                 <td>@episode.Episode.Date.Value.ToString("dd/MM/yyyy")</td>
                 <td><input type="checkbox" value="@episode.Episode.ID" checked="@episode.Watched"/></td>
             </tr>
         }

The user can mark the checkboxes and press a button to submit the info. I'd like to get to see in my controller which checkboxes are marked and which are not.

What's the best way to achieve this?

EDIT:

[HttpPost]
public ActionResult Checkin(IEnumerable<WatchedEpisodeViewModel> episodes)
{
    foreach (WatchedEpisodeViewModel episode in episodes) <-- nullreference exception
    {
        if (episode.Watched)
        {
            // test
        }
    }
    return RedirectToAction("Index", "Home");
}

Upvotes: 1

Views: 103

Answers (2)

Mathew Thompson
Mathew Thompson

Reputation: 56429

The problem is that you're using a foreach loop and not a for loop. You need to use a for loop because that will give the correct index to each of the fields to allow the model binder to do it's stuff.

Another of your problems, is you need to do CheckBoxFor on the Watched bool in your model.

Your final problem, is you haven't got any HiddenFors for your Episode fields, so when you post, you won't know what's been watched as the Episode on each of the items in the model will be null

Try this instead:

@for (int i = 0; i < Model.Count(); i++)
{
    <tr>
        <td>
            @Html.HiddenFor(m => m[i].Episode.ID)
            @Model[i].Episode.ID
        </td>
        <td>
            @Html.HiddenFor(m => m[i].Episode.Name)
            @Model[i].Episode.Name
        </td>
        <td>
            @Html.HiddenFor(m => m[i].Episode.Date)
            @Model[i].Episode.Date.Value.ToString("dd/MM/yyyy")
        </td>
        <td>
            @Html.CheckBoxFor(m => m[i].Watched)
        </td>
    </tr>
}

Upvotes: 2

James South
James South

Reputation: 10635

This is a common problem in MVC as it's difficult bind your list of checkboxes when posting back to your model. Now you could look through the FormCollection but that really isn't effiecient.

I've used this extension before which made the scenario much simpler. CheckBoxList(For) The instructions are pretty straightforward and the package is available on Nuget.

Upvotes: 0

Related Questions