1

I'm creating a ASP.NET MVC 5 SQL Server (Entity Framework, database-first) application where there is an order record and a set of line item records attached to it. The user should be able to add new line item records to the viewmodel through an "Add" button, but the line items should not be committed to the database until the user clicks the "Save" button. Clicking the "Add" button should not refresh the page -- the page should stay exactly where it is, just with the extra rows added.

Right now, I have new rows being added in this way:

View:

@model Models.OrderViewModel
<table style="width: 90%; margin: auto" id="divPartial">
    <tr>
    <th style="width: 25px">
        Header 1
    </th>
    <th style="width: 25px">
        Header 2
    </th>
    <th style="width: 25px">
        Header 3
    </th>
    </tr>


    @if (Model.LineItemRows.Count > 0)
    {
    for (int i = 0; i < Model.LineItemRows.Count; i++)
    {
        @Html.Partial("ViewRow", Model.LineItemRows[i])
    }
    }
</table>

<input type="button" id="mybutton" value="Add New Line Item" class="btn btn-default" />

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
    $(document).ready(function () {
    $("#mybutton").click(function () {
        $.ajax({
            url: "../AddNewLineItem/",
            cache: false,
            type: "POST",
            data: {
            'viewModel': @Html.Raw(Json.Encode(Model)),
            },
            success: function (data) {
            $('#divPartial').append(data);
            },
            error: function (reponse) {
            alert("Error: " + reponse);
            }
        });
        });
    });
</script>

Controller:

[HttpPost]
public ActionResult AddNewLineItem(OrderViewModel viewModel)
{
    OrderLineItemRowViewModel lineItemRow = new OrderLineItemRowViewModel();
    // Set some defaults
    lineItemRow.active = true;
    lineItemRow.location = "I"; 

    if (viewModel.LineItemRows != null) // This shouldn't ever be null
    {
    viewModel.LineItemRows.Add(lineItemRow);
    }

    return PartialView("ViewRow", lineItemRow);
}

When the user clicks on the "Add" button, a jQuery function serializes the current viewmodel and sends it back to the controller. The controller makes a new row with some default options, adds it to the viewmodel rowset that's passed in, then returns a partial view that represents the new row (and sends the data for the new row into the partial view so we know how to populate it).

The thing that's missing from this is...how do I send back the modified viewmodel to the original view? Basically, I've got what should be the current viewmodel in AddNewLineItem() but I have no idea where it needs to be sent.

I'm fairly new to ASP.NET MVC, so my apologies if I'm missing something obvious here.

dev5000
  • 99
  • 2
  • 10

2 Answers2

1

You'd need to create a new partial view that would take your OrderViewModel and generate all of the rows in your table. Move the ajax call to this new partial view. AddNewLineItem would return the new partial view and redraw the entire table and not just one row. This would allow 'viewModel': @Html.Raw(Json.Encode(Model)), to always be current, since it's in the new partial view that gets regenerated each time a row is added

JamieD77
  • 13,796
  • 1
  • 17
  • 27
  • Thank you -- this led me to the answer. Basically, I had to put the "add" button inside of the div as well as return a different type of view (not "ViewRow", but "ViewRows" -- which is the level above "ViewRow"). – dev5000 Jul 30 '15 at 18:25
  • awesome.. i've written something similar just using javascript that allowed adding and deleting, but it was a pain keeping all of the field names in order [0], [1], etc.. and that was also before i knew about `@Html.Raw(Json.Encode(Model))` – JamieD77 Jul 30 '15 at 18:35
0

All you're doing is sending back JSON for your AJAX method right? Here's what I do when sending data back.

If you're serializing the whole form to a controller, then this should work. Have your new controller take all of that serialized data and modify model to be what you want- then return the results back as JSON.

//Controller Code
var model // <-- this is your modified viewModel with the new row in it
var jsonModel = Json(new
            {
                data = model
            }, JsonRequestBehavior.AllowGet);
return jsonModel;

Then it's simply a matter of making your JavaScript/JQuery function consume the json that gets returned.

C. Tewalt
  • 2,271
  • 2
  • 30
  • 49