How to post all table data to MVC controller

How to post all table data to MVC controller

ralphbralphb Posts: 5Questions: 1Answers: 1

I am developing a C# MVC application. I am using a View and Display template to manage the User Interface. The Users are able to edit the data presented on multiple pages. I am having an issue posting the Datatable data from all pages to the Controller. The List object in the Model returned to the Controller contains the correct number of rows, but the column values of all the rows except the rows on the last edited page are null. How do I post all of the data to the Controller?

Code from my View:
@model TreatyMilestonesViewModel
@{
ViewData["Title"] = "Treaty Milestones";
}
<link rel="stylesheet" type="text/css" href="~/lib/datatables/media/css/jquery.dataTables.min.css">

The custom data source library is required for sorting on the check box column


$(document).ready(function () { // DataTables initialisation if (@Model.TreatyMilestonesList.Count() > 1) { $('#TreatyMilestones').DataTable({ "columns": [ { "orderDataType": "dom-checkbox" }, null, null, null, { "orderDataType": "dom-checkbox" }, null ], "columnDefs": [ { "orderable": false, "targets": 5 } ], "order": [[0, 'desc']] }); }; $('#TreatyMilestones').DataTable().on('click', '.rowBinder', function () { //alert("Clicked"); //var oTable = $('#TreatyMilestones').DataTable(); //oTable.search('').columns().search('').draw() //"data": ['#TreatyMilestonesList']; // https://datatables.net/forums/discussion/15667/submit-of-form-containing-datatable-only-includes-values-for-controls-if-previously-changed-page-row // This seems like the answer, but I do not understand how to actually implement it // https://stackoverflow.com/questions/16119693/jquery-data-table-not-working-from-second-page //$('#TreatyMilestones').DataTable(); }); }); function enableFields(assignedMilestone) { var rownum = assignedMilestone.name.match(/(\d+)/g); var sla = '#TreatyMilestonesList_' + rownum + '__TreatyMilestoneSLA'; var inactive = '#TreatyMilestonesList_' + rownum + '__Inactive' $(sla).prop('disabled', !assignedMilestone.checked); $(inactive).prop('disabled', !assignedMilestone.checked); };

@using (@Html.BeginForm())
{

@Model.SelectedTreatyName - Treaty Milestones

@Html.HiddenFor(modelItem => modelItem.SelectedTreatyId)
<table class="table table-striped table-hover row-border order-column oBinder" id="TreatyMilestones">
    <thead>
        <tr>
            <th>@Html.Label("Assigned Milestone")</th>
            <th>@Html.Label("Milestone Description")</th>
            <th>@Html.Label("Milestone SLA")</th>
            <th>@Html.Label("Processing Period")</th>
            <th>@Html.Label("Inactive")</th>
            <th>@Html.HiddenFor(modelItem => modelItem.SelectedTreatyId) @Html.HiddenFor(modelItem => 
                   modelItem.SelectedTreatyName)</th>
        </tr>
    </thead>
    <tbody>
        @Html.DisplayFor(model => model.TreatyMilestonesList)
    </tbody>
</table>

<div class="row">
    <div class="col-lg-2">
        <input type="submit" name="response" value="Save" formaction=@Url.Action("SaveMilestones") formmethod="post" 
           class="btn btn-link" />
    </div>
    <div class="col-lg-10">
        <a asp-action="Index" class="btn btn-link">Back to Treaty Selection</a>
    </div>
</div>

}

Code form my Display Template:
@model MilestoneTracking.Models
.TreatyMilestonesList

<tr class="rowBinder">
<td>
@if (this.ViewContext.HttpContext.Request.Cookies["mtaUserRole"] != "IsAppUser")
{
@Html.CheckBoxFor(modelItem => modelItem.AssignedMilestone, new { onchange="enableFields(this)"})
}
else //This is an "AppUser", do not allow editing
{
@Html.CheckBoxFor(modelItem => modelItem.AssignedMilestone, new { disabled = "disabled" })
}
</td>
<td>@Html.DisplayFor(modelItem => modelItem.MilestoneDescription)</td>
<td>
@if (Model.AssignedMilestone)
{
@Html.TextBoxFor(modelItem => modelItem.TreatyMilestoneSLA, new { type = "number" })
}
else
{
@Html.TextBoxFor(modelItem => modelItem.TreatyMilestoneSLA, new { disabled = "disabled", type = "number" })
}
@Html.ValidationMessageFor(modelItem => modelItem.TreatyMilestoneSLA)
</td>
<td>
@Html.DisplayFor(modelItem => modelItem.ProcessingPeriod)
</td>
<td>
@if (Model.AssignedMilestone)
{
@Html.CheckBoxFor(modelItem => modelItem.Inactive)
}
else
{
@Html.CheckBoxFor(modelItem => modelItem.Inactive, new { disabled = "disabled" })
}
</td>
<td>
These were put here for two reasons;
1. They are within a <td> to eliminiate HTML warning 1503 "Unexpected start tag"
2. They were initially moved within the first column to eliminate the warning, but having them there broke the checkbox
sorting feature hence I moved them to their own cell.

@Html.HiddenFor(modelItem => modelItem.TreatyMilestoneId)
@Html.HiddenFor(modelItem => modelItem.TreatyId)
@Html.HiddenFor(modelItem => modelItem.MilestoneId)
@Html.HiddenFor(modelItem => modelItem.TreatyName)
</td>
</tr>

Code from Controller:
[HttpPost]
public ActionResult SaveMilestones(TreatyMilestonesViewModel _model)
{
// retrieve the as-is state of currently assigned Milestones
List<TreatyMilestone> currentlyAssignedMilestones = GetCurrentlyAssignedMilestones(_model.SelectedTreatyId);
// Let's create this now and we will assign the TreatyId and TreatyName to be passed back to the View after processing is completed
TreatyMilestonesViewModel vm = new TreatyMilestonesViewModel()
{
//SelectedTreatyId = _model.TreatyMilestonesList[0].TreatyId,
//SelectedTreatyName = _model.TreatyMilestonesList[0].TreatyName
SelectedTreatyId = _model.SelectedTreatyId,
SelectedTreatyName = _model.SelectedTreatyName
};

        foreach (TreatyMilestonesList tmlrec in _model.TreatyMilestonesList)
        {
           ...

This question has accepted answers - jump to:

Answers

  • ralphbralphb Posts: 5Questions: 1Answers: 1

    I am attaching a text file with the code. I could not get the code properly formatted in the post.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    You need to use the DataTables API to get the data from all pages as DataTables removes the DOM elements that aren't needed for the current display. If you are using Ajax use rows().data() to get the data, or if you are posting a regular http post, use something like in this example.

    Allan

  • ralphbralphb Posts: 5Questions: 1Answers: 1

    Allan,
    I have been scratching my head on how to get the data formatted in the way the MVC Controller expects it.
    e.g.
    'TreatyMilestonesList': [ { "TreatyMilestoneId": "1", "TreatyId": "1", "MilestoneId": "1", "TreatyName": "Treaty1", "AssignedMilestone": "true", "TreatyMilestoneSLA": "10", "Inactive": "false" }, { "TreatyMilestoneId": "2", "TreatyId": "2", "MilestoneId": "2", "TreatyName": "Treaty2", "AssignedMilestone": "true", "TreatyMilestoneSLA": "20", "Inactive": "false" } ],

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin
    Answer ✓

    Perhaps:

    var object = {
      TreatyMilestonesList: table.rows().data().toArray()
    }
    

    Allan

  • ralphbralphb Posts: 5Questions: 1Answers: 1

    Funny you should suggest that, that is what I was attempting now.

    var treatyMilestonesTable = $('#tableTreatyMilestones').DataTable();
    var tableData = treatyMilestonesTable.rows().data().toArray();

    The result is an [object (Array)] and the data looks like this:
    [0] [<input name="TreatyMilestonesList[0].AssignedMilestone" id="TreatyMilestonesList_0__AssignedMilestone" onchange="enableFields(this)" type="checkbox" alue="true" data-val-required="The AssignedMilestone field is required." data-val="true">,Data Received,<input name="TreatyMilestonesList[0].TreatyMilestoneSLA" disabled="disabled" id="TreatyMilestonesList_0__TreatyMilestoneSLA" type="number" value="0" data-val-required="The TreatyMilestoneSLA field is required." data-val="true" data-val-range-min="-100" data-val-range-max="100" data-val-range="SLA must be in the range of -100 to 100"> <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="TreatyMilestonesList[0].TreatyMilestoneSLA"></span>,M00,<input name="TreatyMilestonesList[0].Inactive" disabled="disabled" id="TreatyMilestonesList_0__Inactive" type="checkbox" value="true" data-val-required="The Inactive field is required." data-val="true">,<input name="TreatyMilestonesList[0].TreatyMilestoneId" id="TreatyMilestonesList_0__TreatyMilestoneId" type="hidden" value=""> <input name="TreatyMilestonesList[0].TreatyId" id="TreatyMilestonesList_0__TreatyId" type="hidden" value="38" data-val-required="The TreatyId field is required." data-val="true"> <input name="TreatyMilestonesList[0].MilestoneId" id="TreatyMilestonesList_0__MilestoneId" type="hidden" value="1" data-val-required="The MilestoneId field is required." data-val="true"> <input name="TreatyMilestonesList[0].TreatyName" id="TreatyMilestonesList_0__TreatyName" type="hidden" value="Test001">]

    Could it be I need a different tool to handle this scenario?

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Oh I see - you want to get the data from inside the input elements? The link I gave above shows how that can be done.

    Allan

  • ralphbralphb Posts: 5Questions: 1Answers: 1
    Answer ✓

    Allan,
    Thank you for your input. We have resolved our issue with the following workaround:
    Javascript
    $('#btnSave').click(function () {
    var oTable = $('#tableTreatyMilestones').DataTable();
    oTable.page.len(200).draw();
    });
    HTML
    <input type="submit" name="response" id="btnSave" value="Save" formaction=@Url.Action("SaveMilestones") formmethod="post" class="btn btn-link" />

This discussion has been closed.