TomJerrum
TomJerrum

Reputation: 614

Razor checkboxes for list of models

User Model

public class UserModel
{
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Location { get; set; }
    public IEnumerable<UserPets> UserPets { get; set; }
}

User Pets Model

public class UserPetsModel
{
    public PetModel Pet{ get; set; }
    public bool UserHasPet { get; set; }
}

Using these 2 models I am creating an edit page where a User can come in and edit which Pets they have.

To enable them to state which pets they have I am trying to use checkboxes.

Edit Page

@model Models.UserModel

@using (Html.BeginForm())
{
   <div class="form-group">
        @Html.LabelFor(model => model.FirstName)
        @Model.FirstName
   </div>

    @foreach (var userPets in Model.UserPets)
    {
        @Model.Pet.AnimalName
        <div>
            @Html.CheckBoxFor(u => userPets .UserHasPet)
        </div>
    }

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
}

The problem I am having is when trying to map the UserModel back to the controller action. When I press the save button, everything on the UserModel is being mapped back to the controller apart from the UserPetsModels which I believe is due to the use of the foreach.

Is there another way in which I can display a checkbox for each UserPetModel without using a foreach or a for loop.

Upvotes: 2

Views: 2104

Answers (2)

teo van kot
teo van kot

Reputation: 12491

Yes there is. You should create EditorTemplate for your UserPetsModel. It will look like:

 @model UserPetsModel

 @Model.Pet.AnimalName
 <div>
     @Html.CheckBoxFor(model => model.UserHasPet)
 </div>

And then you can simply do:

@Html.EditorFor(model => model.UserPets)

EditorFor will create right binding for you. Note that you should create EditorTemplate only for UserPets and it also will work for List<UserPetsModel> and IEnumarable<UserPetsModel> with the same syntax that i show.

Upvotes: 3

SBirthare
SBirthare

Reputation: 5137

I would suggest replace the loop with EditorTemplate. So your

@foreach (var userPets in Model.UserPets)
    {
        @Model.Pet.AnimalName
        <div>
            @Html.CheckBoxFor(u => userPets.UserHasPet)
        </div>
    }

would look like:

   <div class="row">
      @Html.EditorFor(m => m.UserPets)
   </div>

And define a view in (~/Views/Shared/EditorTemplates/UserPets.cshtml) like:

@model UserPetsModel
@Html.HiddenFor(x => x.Pet.PetId)

@Html.LabelFor(x => x.UserHasPet, Model.Pet.AnimalName)
@Html.CheckBoxFor(x => x.UserHasPet)

Upvotes: 1

Related Questions