如何从 table 以编程方式 add\delete 行,该 table 与 Asp.NET MVC 中控制器的模型数据绑定

How to add\delete rows programatically from a table that binds with model data from controller in Asp.NET MVC

我有一个 Asp.NET MVC 页面,它有一个类似

的模型
namespace Sample.Models
{
    public class ContModel
    {
        [Display(Name = "Name")]
        public string Name { get; set; }

        [Display(Name = "Code")]
        public string Code { get; set; }

        [Display(Name = "Customer")]
        public string Customer { get; set; }

        public List<Order> Orders { get; set;}
    }

    public class Order
    {
        public string OrderId;
        public string OrderDesc;
    }
}

我已经使用本文成功绑定了模型数据 https://www.pluralsight.com/guides/asp.net-mvc-getting-default-data-binding-right-for-hierarchical-views

文中给出的例子使用 for循环和@Html.TextBoxFor形成table。现在我想以编程方式 add\delete 行。

到目前为止,我提到的所有示例都是使用 jQuery 插入行。所有 table 行都形成为 JSON 字符串,并使用 AJAX 调用传递给控制器​​。

AJAX 是唯一的方法吗?。是否有一种正确的方法来绑定新添加的行的数据,以便它会自动传递给使用 POST 的表单提交?

好的,首先,免责声明:我没有测试下面的代码,它可能有点不完整,可能无法开箱即用。但主要概念都在那里,我认为只要稍加应用思考,您就可以到达您想去的地方。

此外,如果在模型绑定期间绑定到列表的项目的索引值不按顺序或丢失(例如,如果您有一个包含 3 个订单和删除索引为 2 的行,您将得到一个索引为 1 和 3 的列表,它如何创建缺少 2 的列表 - 您必须自己检查。)

如果您对其进行测试并发现存在问题,那么您可能不得不重新考虑我快速尝试存储计数器变量的尝试,并可能重新索引现有 html 中的项目名称行被删除。 - 如果你在你的 javascript 中使用一个全局变量,你可能可以完全取消计数器变量,这将在该页面的整个生命周期中保持价值,但是我已经有一段时间没有做过类似的事情了虽然我似乎记得它在工作,但我不能肯定地说。

正在删除: 对于删除,您需要知道 什么 被删除了。很快就会想到两种方法;

  1. 一旦你的控制器中有了模型,你就可以检查你的数据库,哪些项目在你的数据库中,哪些不在列表中,然后从来自数据库的列表。

  2. 当一个项目被删除时,您将 OrderId 存储在另一个隐藏的输入中,以逗号分隔的字符串形式,如“3,25,100”,并将其绑定到您的模型。这样,当你的控制器中有模型时,你可以只用逗号分隔,循环遍历数组并删除相应的订单。

我相信还有很多其他方法可以做到这一点。

<table>
    <thead>
        <tr>
            <th></th>
            <th>Description</th>
            <th><button id="AddOrder">Add Order></button></th>
        </tr>
    </thead>
    <tbody id="tableBody">
@for (int i = 0; i < Model.Orders.Count(); i++)
{
    var item = Model.Orders[i];

        <tr id="Order-@item.OrderId">
            <td>
                <button type="button" data-id="@item.OrderId" class="removeOrderBtn"></button>
                @* The trick to model binding with a list is the name attribute matching the Property Name on the model and giving it an index as below *@
                <input type="hidden" name="Orders[@i].OrderId" value="@item.OrderId" />
            </td>
            <td>
                @item.OrderDesc
                <input type="hidden" name="Orders[@i].OrderDesc" value="@item.OrderDesc" id="OrderDesc-@item.OrderId" />
            </td>
        </tr>

}
    </tbody>
</table>
@*Store the value of the last index in this input to keep track of it constantly*@ 
<input type="hidden" id="count" value="@(Model.Orders.Count()-1)">


<script type="text/javascript">

    $("#AddOrder").on('click', function (e) {

        //get the counter input and store it because we're going to update the value later.
        var counterInput = $("#count");
        var counter = counterInput.val();
        counter++;
        //Assumed your new order description has an id of description.
        var description = $("#description").val();
        //Again you need to prepare your html so that the model binding will work by forming the name correctly.
        var newRow = "<tr><td><input type='hidden' name='Orders[" + counter + "].OrderId' value='0' /></td><td <input type='hidden' name='Orders[" + counter + "].OrderDesc value=" + description +" /></td></tr>";
        var tableBody = $("#tableBody");
        //Append the new tr to the table body after the other rows (might be a better way to do this with append or something similar).
        tableBody[0].innerHTML = tableBody[0].innerHTML + newRow;

        //Update the counter stored in the input so that we can keep track of how many items we have in the list to try avoid duplicate numbers
        counterInput.val(counter);
    });

    $(".removeOrderBtn").on('click', function (e) {
        var id = e.target.dataset.id;

        var tableBody = $("#tableBody");
        tableBody.remove("#Order-" + id); // I think this takes a selector.
        var counterInput = $("#count");
        var counter = counterInput.val();
        counter--;
        counterInput.val(counter);

    });

</script>

如果您有任何问题,请告诉我。

试试这个,希望对你有用

<script src="//jsfiddle.net/mustafaozkaya/nfxz4ep2/18/embed/"></script>