1

So I have a view which is currently displaying a table of data from the database with a select/selectall checkbox in place. What I'd like to do is be able to get a list of my CustomerNumbers and whether or not they have been checked and return it to my controller for further action.

enter image description here

Below is my how my view is currently written. I have tried numberous ways to get this to work and I am stumped.

@model MassInactiveInspections.Models.CustomerInfoList

<div class="container">
    <h2>@ViewBag.Title</h2>
    <div class="bs-callout bs-callout-info" style="margin-bottom: 0px;">
    </div>
    <div class="col-md-8">

            @using (Html.BeginForm("SelectedCustomers", "Home", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()
                <hr />
                @Html.ValidationSummary(true)
                <div class="form-group">
                    <table class="table table-bordered">
                        <tr>
                            <th class="active">@Html.DisplayName("Select All?")<input type="checkbox" class="select-all checkbox" name="select-all" /></th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().BusinessName)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().CustomerName)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().CustomerNumber)</th>                              
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().InspectionCycleDescription)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().LastInspectionDate)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().RouteCode)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().RouteID)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().SiteNumber)</th>
                            <th>@Html.DisplayNameFor(m => m.CustomerInfoListView.FirstOrDefault().SystemCode)</th>
                        </tr>

                        @foreach (var item in Model.CustomerInfoListView)
                        {
                            <tr>
                                <td class="active"> <input id="Selected" input type="checkbox" class="select-item checkbox" name="select-item" value="1000" /> </td>
                                <td>@Html.DisplayFor(modelItem => item.BusinessName)</td>
                                <td>@Html.DisplayFor(modelItem => item.CustomerName)</td>
                                <td>
                                    @Html.DisplayFor(modelItem => item.CustomerNumber)
                                    @Html.HiddenFor(m => m.CustomerInfoListView.FirstOrDefault().CustomerNumber)
                                </td>
                                <td>@Html.DisplayFor(modelItem => item.InspectionCycleDescription)</td>
                                <td>@Html.DisplayFor(modelItem => item.LastInspectionDate)</td>
                                <td>@Html.DisplayFor(modelItem => item.RouteCode)</td>
                                <td>@Html.DisplayFor(modelItem => item.RouteID)</td>
                                <td>@Html.DisplayFor(modelItem => item.SiteNumber)</td>
                                <td>@Html.DisplayFor(modelItem => item.SystemCode)</td>
                            </tr>
                        }
                    </table>
                </div>
                <div class="form-group">
                    <div style="margin-top: 50px">
                        <input type="submit" id="btnLost" class="btn btn-primary" value="Lost"/>
                        <input type="submit" class="btn btn-primary" name="OOBButton" value="OOB" />
                        <input type="submit" class="btn btn-primary" name="RefusedButton" value="Refused" />
                    </div>
                </div>
                }
    </div>
</div>

and finally my controller

[HttpPost]
public ActionResult SelectedCustomers(CustomerInfoList 
customerNumberList)
{
    return View("ViewCustomerInfo");
}

also here is my javascript for the checkboxes

[HttpPost]
public ActionResult SelectedCustomers(CustomerInfoList customerNumberList)
{
    return View("ViewCustomerInfo");
}


        //column checkbox select all or cancel
$("input.select-all").click(function () {
    var checked = this.checked;

    $("input.select-item").each(function (index, item) {
        item.checked = checked;
    });
});

//check selected items
$("input.select-item").click(function () {
    var checked = this.checked;
    console.log(checked);
    checkSelected();
});

//check is all selected
function checkSelected() {
    var all = $("input.select-all")[0];
    var total = $("input.select-item").length;
    var len = $("input.select-item:checked:checked").length;
    console.log("total:" + total);
    console.log("len:" + len);
    all.checked = len === total;
}
});
snapper
  • 210
  • 3
  • 14
  • 2
    Seems like you need a new property on your `CustomerInfoListView` view model named `Selected`, then where your `` is you can use `@Html.EditorFor(m => m.CustomerInfoListView[i].Selected)` in your loop (where `i` is the index position of that item). Then you would have access to that data when you post to your controller. – zgood Jul 25 '17 at 18:33
  • You cannot use a `foreach` loop for generating form controls for a collection - refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943). And to handle your checkboxes and post back the selections - refer [this answer](https://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416#29554416). And you will need some javascript to handle your 'Select All' checkbox –  Jul 25 '17 at 23:08
  • @StephenMuecke Could he keep the `foreach` and use `var i = Model.CustomerInfoListView.IndexOf(item);` to get his index position for each iteration? – zgood Jul 26 '17 at 02:06
  • @zgood, No that will not work. It will not generate the correct `name` attribute for binding (which needs to be `name="CustomerInfoListView[0].CustomerNumber"`, `name="CustomerInfoListView[1].CustomerNumber"` etc. –  Jul 26 '17 at 02:12
  • @StephenMuecke I think you misunderstood what I was asking. Please look at the [fiddle](https://dotnetfiddle.net/PU99hw) (just the Razor part with the `foreach` loop). You see I can use a `foreach` and still get the index value to generate the correct names with the `@Html` Razor helpers. I know that works I have used it successfully before, I was more or less wondering if it was less efficient than a normal `for` with an `i++`. I am just trying to show you that you **can** use a `foreach` to generate controls for a collection, you just have to manage the index value yourself – zgood Jul 26 '17 at 12:26
  • @zgood That's just adding unnecessary code to mimic using a `for` loop, and it will only work if the model is `IList` so what would be the point. And your fiddle does not even compile :) –  Jul 26 '17 at 12:31
  • Well you could `.ToList` it or setup your own `var i = 0;` and `i++` each iteration. I agree that a normal `for` is more suited... I'm just show you that you can do it. So when you say _cannot_ you really mean _shouldn't_ ;) (Oh I didn't make the fiddle to compile lol... just to show some Razor... I didn't touch the controller or VM) – zgood Jul 26 '17 at 12:33
  • @zgood, You can shoot yourself in the foot too. Why would you want to? And the _cannot_ was in relation to the question –  Jul 26 '17 at 13:08
  • I really appreciate the responses and am working through them. I added the javascript for the checkboxes. Thanks again. – snapper Jul 26 '17 at 13:16

1 Answers1

0

Not sure if it is the best way to handle it but I simply added the fields that I wanted into a HiddenFor helper and they were returned to my the appropriate controller. Thanks everyone for the help.

 @Html.HiddenFor(m => m.additionalCustomerInfoListView[i].CustomerNumber)
snapper
  • 210
  • 3
  • 14