我正在寻找有关如何在ASP.Net MVC 5应用程序的create Razor视图中向Invoice添加新行LineItem的帮助。我已经阅读了几乎所有类似的问题,但没有一个解决了我认为是一个简单的用例。
这是我的发票模型类
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>();
}
请注意,此发票包含LineItem列表,每个行Item都是一个简单对象。并在Invoice构造函数中创建一个行项列表。这是LineItem模型类
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; }
}
生成的ASP.Net MVC 5 Razor视图无法识别对象的LineItems列表,也没有为其创建任何条目。我想动态地向下面的表添加一行,我想让该行成为一个Line项的实例。
这是显示发票的表格
<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>
这是我尝试使用JQuery动态地向该表追加一行,而这就是我被困住的地方,任何帮助或指针都会非常感激。
<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>
我不会通过你描述的方式修改dom来动态地做这种事情。我倾向于在剃刀视图中生成所有必要的代码,就好像它始终存在,然后只需切换行本身的可见性。通过这种方式,文本框在生成视图时可以正确呈现为表单元素,并且您仍然可以使用jQuery修改表,等待任何AJAX请求。
另外,您所描述的行为听起来像是在尝试添加更多客户端行为并减少到服务器的往返次数/大小。如果这是真的,我建议探索一个JavaScript MVVM框架,如Knockout,Ember或Angular。
您可以创建动态行,但根据我的经验,它们不会绑定到模型。我有一个下拉列表,用户选择一个资产编号,然后单击“添加”按钮,动态地向表中添加一行。
我所做的是在表中创建一个隐藏的行来使用模板。
<table class="table table-bordered table-condensed table-hover" id="lineItemTable" name="assetTable">
<thead>
<tr>
<th class="text-center">Item #</th>
<th class="text-center">Asset</th>
<th class="text-center">Condition</th>
<th class="text-center">Description 1</th>
<th class="text-center">Description 2</th>
<th class="text-center">Inventory Num</th>
<th class="text-center">Serial Number</th>
</tr>
</thead>
<tbody>
<tr hidden>
<td>
<label id="row"></label>
</td>
<td>
<input asp-for="TransferLineItem.AssisAsset" class="form-control" [email protected] />
</td>
<td>
<select asp-for="TransferLineItem.Condition" class="form-control" asp-items="@ViewBag.Conditions"></select>
</td>
<td>
<input asp-for="TransferLineItem.AssetDescription1" class="form-control" [email protected] />
</td>
<td>
<input asp-for="TransferLineItem.AssetDescription2" class="form-control" [email protected] />
</td>
<td>
<input asp-for="TransferLineItem.InventoryNum" class="form-control" />
</td>
<td>
<input asp-for="TransferLineItem.SerialNumber" class="form-control" [email protected] />
</td>
</tr>
</tbody>
</table>
单击添加按钮时,我使用jQuery克隆隐藏的表行,并使用新行追加表。我使用'_ [行号]'附加每个控件的id,以便每个控件都有一个唯一的ID号。
//clones the first row of the table
var newRow = $("#lineItemTable tbody tr").first().clone();
//removes the 'hidden' attribute so it will be visible when added to the table
newRow.removeAttr("hidden");
//add/append new row to the table
$("tbody").append(newRow);
//get row number which will be appended to the id of each control in this row
//for example if this were the second row then the id of the asset field would be something like asset_2.
//note that since there is already a hidden row in the table, we subtract 1 from the row number
var rowNum = "_" + ($("#lineItemTable tbody tr").length-1);
//loop through the input controls and add the new id value
newRow.find("input").each(function () {
// get id of the input control
var ctrl = $(this).attr("id");
//concatenate the row number to the id
var newId = ctrl + rowNum;
//assign new id to control
$(this).attr("id", newId);
});
为了将数据保存在html表中,我使用jQuery为每一行创建一个名称 - 值对数组,并将其传递给控制器中的函数。
//get table
var tbl = document.getElementById("lineItemTable");
//array to hold the json objects
var jsonArray = [];
//iterate through the fields and put values in the json object
for (var i = 1, r = tbl.rows.length-1; i < r; i++)
{
var jsonObj = {
asset: $("#TransferLineItem_AssisAsset_" + i).val(),
condition: $("#TransferLineItem_Condition_" + i).val(),
assetDescription1: $("#TransferLineItem_AssetDescription1_" + i).val(),
assetDescription2: $("#TransferLineItem_AssetDescription2_" + i).val(),
InventoryNum: $("#TransferLineItem_InventoryNum_" + i).val(),
serialNumber: $("#TransferLineItem_SerialNumber_" + i).val()
};
//put json object in array
jsonArray.push(jsonObj);
}
//pass json array to controller function to save line items
$.ajax({
type: "GET",
url: "Create?handler=SaveTransferLineItems",
contentType: "application/json; charset=utf-8'",
data: { jsonObj: JSON.stringify(jsonArray) },
success: function () {
showModal("btn-success", "Form Saved", "Your new transfer form was successfully saved.");
},
failure: function () {
showModal("btn-danger", "Save Failed", "Your form could not be saved, please contact site support");
}
});
在控制器函数中,我将名称值对转换为类型为“TransferLineItem”的列表,即绑定模型。我可以迭代列表并使用上下文保存到数据库。
dynamic _json = JsonConvert.DeserializeObject<List<TransferLineItem>>(jsonObj);
foreach (TransferLineItem item in _json)
{
try
{
_context.TransferLineItem.Add(item);
int x = await _context.SaveChangesAsync();
if (x != 1)
{
ModalMessage = "Could not save items, starting at " + TransferLineItem.Asset;
return Page();
}
}
catch (Exception ex)
{
ModalType = "btn-danger";
ModalTitle = "Save Failed";
ModalMessage = ex.Message;
return Page();
}
}