I am looking for help on how to add a new row of LineItems to an Invoice in a create Razor view of an ASP.Net MVC 5 application. I have read almost all similar questions but none have addressed what I thought was a simple use case.
Here is my Invoice model class
public class Invoice
{
public int Id { get; set; }
public int InvoiceNumber { get; set; }
public List<LineItem> LineItems { get; set; }
public Client Customer { get; set; }
public DateTime DateCreated { get; set; }
public decimal Total { get; set; }
public Invoice()
{
LineItems = new List<LineItem>();
}
Take note that this invoice contains a List of LineItems and each line Item is a simple object. And a List of line items is created in the Invoice constructor. Here is the LineItem model class
public class LineItem
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Total { get; set; }
}
The generated ASP.Net MVC 5 Razor views did not recognize the LineItems list of the object and did not create any entry for it. I want to dynamically add a row to the table below and I want to make that row an instance of Line items.
Here is the Table showing the invoice
<table class="table table-condensed" id="invoiceTable">
<thead>
<tr id="invoiceTableHead">
<td><strong>Item Name</strong></td>
<td class="text-center"><strong>Item Description</strong></td>
<td class="text-center"><strong>Item Price</strong></td>
<td class="text-center"><strong>Item Quantity</strong></td>
<td class="text-right"><strong>Total</strong></td>
</tr>
</thead>
<tbody>
And here is my attempt at using JQuery to append a row to this table dynamically and I that is where I am stuck, any help or pointers that will be greatly appreciated.
<script type="text/javascript">
$("#lineItemButton").click(function () {
debugger;
// Create elements dynamically
var newRow = "<tr><td>'@Html.TextBoxFor(x => x.LineItems, new { ??? What do int public here)'</td></tr>";
// Add the new dynamic row after the last row
$('#invoiceTable tr:last').after(newRow);
});
</script>
You can create dynamic rows, but from my experience they will not bind to the model. I have a drop down that the user selects an asset number and clicks an 'Add' button that adds a new row, dynamically, to the table.
What I did was create a hidden row in a table to use a template.
When the add button is clicked I use jQuery to clone the hidden table row and append the table with the new row. I append the id of each control with '_[row number]' so that each control had a unique id number.
To save the data in the html table, I use jQuery to create an array of name-value pairs for each row, and pass that to a function in the controller.
In the controller function, I convert the name value pairs to a list of type 'TransferLineItem', a bound model. I can iterate over the list and use context to save to the database.
I would not do this sort of thing dynamically by modifying the dom in the manner you describe. My preference would be to generate all of the necessary code in the razor view as if it was always there and then simply toggle the visibility of the row itself. This way the textbox is rendered properly as a form element when the view is generated, and you still have full access to modify the table with jQuery pending any AJAX requests.
On a side note, the behavior you're describing makes it sound like you're attempting to add more client side behaviors and reduce the number/size of the round trips to the server. If this is true, I would suggest exploring a JavaScript MVVM framework like Knockout, Ember or Angular.