Phill Greggan
Phill Greggan

Reputation: 2394

why checkbox wont check on page load?

i have the following database table for the Compounds table (chemical compounds/elements in the periodic table) there are typos in table data so ignore them

enter image description here

the data is :

enter image description here

the controller :

    public class CheckboxController : Controller
    {
        //
        // GET: /Checkbox/
        testdbEntities db = new testdbEntities();

        [HttpGet]
        public ActionResult Index()
        {
            var comps = db.Compounds.Select(c => new CompoundModel { Id=c.Id, CompoundName=c.Name, IsSelected=c.IsSelected}).ToList();

            CheckboxVM cvm = new CheckboxVM { checkboxData=comps};

            return View(cvm);
        }

        [HttpPost]
        public string Index(IEnumerable<CheckboxVM> collection)
        {
            return "";
        }
}

Model class CompoundModel is:

public class CompoundModel
{
    public int Id { get; set; }
    public string Code { get; set; }


    public string CompoundName { get; set; }
    public bool IsSelected { get; set; }
}

and the ViewModel CheckBoxVM:

public class CheckboxVM
{        
    public string Id { get; set; }
    public string CompoundNmae { get; set; }        
    public bool IsSelected { get; set; }        
    public IEnumerable<CompoundModel> checkboxData { get; set; }   
}

When the page loads it should display check boxes with names and if db table has checked on them (IsSelected=1) then they should be checked.In the post back i need to receive the id, of the user checked checkboxes. At the moment my code does meet the first requirement to check the checked checkboxes based on IsSelected on page load. Is there a way to fix this?

If you need a video with debugging please ask i will be happy to post : )

THE VIEW: (UPDATE)

@model recitejs1.Models.CheckboxVM

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

    @using (Html.BeginForm())
    {   
        foreach (var item in Model.checkboxData)
        {



            @Html.CheckBoxFor(x=>x.IsSelected, (item.IsSelected)?new{@checked="check"}:null)@item.CompoundName

            @Html.HiddenFor(x=>x.Id, item.Id)
            @Html.HiddenFor(x=>x.CompoundNmae, item.CompoundName)

        }
        <br><br>
        <input type="submit" name="name" value="Send" />
    }

Upvotes: 0

Views: 194

Answers (1)

user3559349
user3559349

Reputation:

You cannot use a foreach loop to generate form controls. It generates duplicate name attributes (that have no relationship to your model) and duplicate id attributes (invalid html).

Create a custom `EditorTemplate for your model

In /Views/Shared/EditorTemplates/CompoundModel.cshtml

@model recitejs1.Models.CompoundModel
@Html.HiddenFor(m => m.Id)
@Html.HiddenFor(m => m.CompoundName)
@Html.CheckBoxFor(m => m.IsSelected)
@Html.LabelFor(m => m.CompoundName)

Then in the main view

@model recitejs1.Models.CheckboxVM
....
@using (Html.BeginForm())
{
  @Html.EditorFor(m => m.checkboxData)
  <input type="submit" name="name" value="Send" />
}

The EditorFor() method will generate the correct html for each item in your collection

Note: You should inspect the html before and after you make this change to better understand how model binding works.

Note also that your POST method parameter needs to be

public string Index(CheckboxVM model)

since that's what the view is based on. However the only property of CheckboxVM that you use in the view is IEnumerable<CompoundModel> checkboxData in which case your view should be

@model IEnumerable<CompoundModel>
...
@Html.EditorFor(m => m)

and keep the POST method as it is (but change the GET method)

Upvotes: 2

Related Questions