如何在ASP.Net MVC 5中动态添加新行

时间:2015-02-24 08:48:20

标签: asp.net-mvc razor asp.net-mvc-5

我正在寻找有关如何在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列表,每行项目都是一个简单对象。并在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列表,也没有为其创建任何条目。我想动态地向下面的表添加一行,我想让该行成为行项目的实例。

以下是显示发票的表格

<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>

2 个答案:

答案 0 :(得分:1)

我不会通过你描述的方式修改dom来动态地做这种事情。我倾向于在剃刀视图中生成所有必要的代码,就好像它始终存在,然后只需切换行本身的可见性。通过这种方式,文本框在生成视图时可以作为表单元素正确呈现,并且您仍然可以使用jQuery修改表,等待任何AJAX请求。

另一方面,您所描述的行为使您听起来像是在尝试添加更多客户端行为并减少到服务器的往返次数/大小。如果这是真的,我建议探索一个JavaScript MVVM框架,如Knockout,Ember或Angular。

答案 1 :(得分:0)

您可以创建动态行,但是根据我的经验,它们不会绑定到模型。我有一个下拉菜单,用户选择一个资产编号,然后单击“添加”按钮,该按钮会向表中动态添加新行。

我所做的是在表中创建一个隐藏行以使用模板。

   <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" value=@ViewBag.AssisAsset />
                        </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" value=@ViewBag.AssetDescription1 />
                        </td>
                        <td>
                            <input asp-for="TransferLineItem.AssetDescription2" class="form-control" value=@ViewBag.AssetDescription2 />
                        </td>
                        <td>
                            <input asp-for="TransferLineItem.InventoryNum" class="form-control"  />
                        </td>
                        <td>
                            <input asp-for="TransferLineItem.SerialNumber" class="form-control" value=@ViewBag.SerialNum />
                        </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();
            }


        }