user4864716
user4864716

Reputation:

How to mass update a table in MVC view instead of one record at a time?

I am presenting the question with the wording shown so that it indicates what I am really trying to do. While I could present the question as, "How can I use jQuery to read a table's contents an convert to type IEnumerable<ModelName>?" I would be hiding important context that could suggest a far better way of achieving this outcome, which is what I'm really hoping for.

When auto-scaffolding a controller and views from a model (using Entity Framework), the resulting view allows one to edit one record at a time by clicking the row, editing the record, and returning to the Index. For many cases that is the desired functionality.

But what about when one wants to mass-update values in a table, as if one were working on a spreadsheet. For example, toggle some checkboxes and click "Update", like in this scenario.

enter image description here

One working idea I have is to use jQuery to:

  1. Read the table data and convert into a variable of type IEnumerable<SampleModel>.
  2. Pass the table contents to a public void method in the controller.
  3. Notify the user that the action was successful and refresh the page.

It's really #1 where I am stuck because I need to be able to pass an object of type IEnumerable<SampleModel> to the controller's method, and I do not know how to do this.

Controller:

public void UpdateTable(IEnumerable<SampleModel> query)
{
    // I'm verifying existence before writing code here.
    // This is where I'll be updating the database.
    Debug.WriteLine("Test for query existence " + query.Count());
}

View:

@model SampleSystem.Areas.FakeName

<button id="UpdateTableTop">Update</button>

<table class="table">
    <tr>
        <th></th>
        <th>
            @Html.DisplayNameFor(model => model.Reconciled)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.StudentID)
        </th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.HiddenFor(modelItem=>item.ID)
            </td>
            <td>                    
                @Html.CheckBoxFor(modelItem => item.Reconciled)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.StudentID)
            </td>               
        </tr>
    }
</table>

@section scripts {
    <script>
        $(function () {
            $("UpdateTableTop").click(function (e) {                
                $.ajax({
                    url: '@Url.Action("UpdateTable")',
                    data: 
                    /* ...  Need to convert table 
                     *      to IEnumerable<SampleModel>  ...
                    */,
                    success: function (){
                        console.log("Success!");
                    }
                });
            });
        });
    </script>
}

Upvotes: 1

Views: 1598

Answers (2)

bvoleti
bvoleti

Reputation: 2552

One more possible approach in addition to previous answer. Add data attribute to the checkbox

@Html.CheckBoxFor(modelItem => item.Reconciled, new { data_myid = item.ID }) /* the _ gets converted to - */

Later, use jQuery to retrieve all checked checkboxes.

var selectedIds = new Array();
$( "input:checked" ).each(function(eachCheckbox){
    selectedIds.push($(eachCheckbox).data('myid'));// could serialize to JSON but if the update action is the same for all id's then there is no need for additional data transfer
});

Then pass selectedIds as your data in ajax call and notify on success.

On the server side:

public void UpdateTable(IEnumerable<int> query) /* change type to int */
{
    Debug.WriteLine("Test for query existence " + query.Count());
}

Upvotes: 1

Andy T
Andy T

Reputation: 9881

This is not a complete answer, but should lead you in the correct direction.

        $("UpdateTableTop").click(function (e) {                
           var selectedModels = [];

           // Get all of the rows that were selected

           // Loop through each row, create an object and add to array
           for(var i = 0; i < numItemsSelected; i++)
           {
              // Make sure the properties of the model match your definition of SampleModel
               var currentModel = {
                                      Reconciled = ??? , //Reconciled from the current row
                                      StudentID = ???
                                   };
               selectedModels.push(currentModel);
           }

            $.ajax({
                url: '@Url.Action("UpdateTable")',
                data: /* pass in the list of models (selectedModels) */,
                success: function (){
                    console.log("Success!");
                }
            });
        });

On the server-side, model-binding will take care of creating the SampleModel based on the posted values.

Upvotes: 1

Related Questions