0

This is quite simple situation actually, but I can't get how to make this work. So, there is list of checkboxes rendered in PartialView. Data passed from parent ViewModel to child ViewModel in PartialView. All these wrapped by form, unfortunately I can't get the data from PartialView.
Parent ViewModel:

public class UserProgramsViewModel
    {
        public int Id { get; set; }
        [Required(ErrorMessage = "Введите название")]
        [DisplayName("Название")]
        public string ProgramName { get; set; }
        [DisplayName("Пользователь")]
        public string UserName { get; set; }
        [DisplayName("Пользователь")]
        public int UserId { get; set; }
        [DisplayName("Дни Программы")]
        public ICollection<ProgramDaysDTO> ProgramDays { get; set; }
        public IEnumerable<DaysViewModel> Days { get;  set;} //Passed to Partial
    }

Child ViewModel:

public class DaysViewModel
    {
        public int Id { get; set; }
        public string DayName { get; set; }
    }

Parent View:

@Html.Partial("Days", Model.Days)

PartialView (here we are using attribute name 'Days' to bind it to Parent model)

@model IEnumerable<BBN.Admin.ViewModels.DaysViewModel>
<ul class="list-group col-lg-2">
    @foreach (var item in Model)
    {
        <li class="list-group-item"><input type="checkbox" name="Days" value="@item.Id" /> @item.DayName</li>
    }
</ul>

Controller:

        [HttpPost]
        [RBAC]
        public async Task<ActionResult> Create(UserProgramsViewModel model)
        {
            var groups = await _us.GetAll();
            ViewBag.Users = groups.Select(x => new SelectListItem
            {
                Text = x.Login,
                Value = x.Id.ToString()
            });
            var dto = new UserProgramsDTO
            {
                ProgramName = model.ProgramName,
                UserId = model.UserId,
                Days = model.Days
            };
            var result = await _ps.Create(dto);
            if (result.IsSuccess == (BLL.Utilities.Enums.IsSuccess)Enums.IsSuccess.Success) return RedirectToAction("Index");
            else return View("Create");
        }
andrey.shedko
  • 3,128
  • 10
  • 61
  • 121
  • 1
    `Days` is a complex object and you cannot bind a checkbox to a complex object. Nor can you use a `foreach` loop to generate form controls for a collection. You need a view model and a `for` loop similar to [this answer](http://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416#29554416) –  May 05 '16 at 05:23
  • Guys, thanks for ideas, let me try few solutions. – andrey.shedko May 05 '16 at 05:55

2 Answers2

1

You can use FormCollection. Assign item.DayName to input's name attribute:

PartialView(fragment):

<li class="list-group-item">
      <input type="checkbox" name="@(item.DayName)Days" @if (item.Id > 0) { <text>checked</text> } /> @item.DayName
</li>

Then process FormCollection parameter and fill model's Days property with it's help:

Controller:

[HttpPost]
[RBAC]
public async Task<ActionResult> Create(UserProgramsViewModel model, FormCollection formCollection)
{
    model.Days = new List<DaysViewModel>();
    foreach(var key in formCollection.AllKeys.Where(x => x.Contains("Days")))
        model.Days.Add(new DaysViewModel { Id = formCollection[key] == "on" ? 1 : 0, DayName = key.Replace("Days", "")} );

     //other stuff...
}
Slava Utesinov
  • 13,410
  • 2
  • 19
  • 26
0

Have you set values for "Days" in your parent view from controller? like Suppose your parent view name is "Parent" then you should write like this,

public ActionResult Parent()
{
     UserProgramsViewModel loUser = new UserProgramsViewModel(); 
       //Assign Your values here

     View(loUser); 
}

So may be you will not get Null value here.

Kinjal Gohil
  • 958
  • 9
  • 15