Add row in table with jquery which is connected wi

2019-03-19 17:04发布

问题:

I have this table and shows values from the server. How I can with jquery add a new row in this table if I want to send values from the table to the Server

<table id="Products" class="Products">
    <tr>
        <th>ProductId</th>
        <th>Productname</th>
        <th>Quantity</th>
        <th>UnitPrice</th>
    </tr>

    @for (int i = 0; i < Model.NorthOrderDetails.Count; i++)
    {
        <tr>
            @Html.HiddenFor(m => m.NorthOrderDetails[i].ProductID)
            @Html.HiddenFor(m => m.NorthOrderDetails[i].ProductName)
            <td>@Html.DisplayFor(m => m.NorthOrderDetails[i].ProductID)</td>

            <td>@Html.DisplayFor(m => m.NorthOrderDetails[i].ProductName)</td>

            <td><input type="hidden" name="NorthOrderDetails.Index" value="@i" /> </td>

            <td> @Html.TextBoxFor(m => m.NorthOrderDetails[i].Quantity) </td>

            <td> @Html.TextBoxFor(m => m.NorthOrderDetails[i].UnitPrice, String.Format("{0}", Model.NorthOrderDetails[i].UnitPrice))</td>
            <td>
                <button type="button" class="delete" data-id="@Model.NorthOrderDetails[i].ProductID">Delete</button></td>
        </tr>
    }
</table>    

回答1:

You can use the BeginCollectionItem html helper a partial view for your model to generate collection items with unique indexers and allow binding to the collection on post back. Note you have not indicate the type of property NorthOrderDetails, but form your previous questions, I assume its NorthOrderDetails.cs

Create a partial for NorthOrderDetails.cs

Views/YourController/_NorthOrderDetails.cshtml

@model NorthOrderDetailscs
@using(Html.BeginCollectionItem()) 
{
  <tr>
    @Html.HiddenFor(m => m.ProductName)
    <td>@Html.DisplayFor(m => m.ProductID)</td>
    <td>@Html.DisplayFor(m => m.ProductName)</td>
    <td>@Html.TextBoxFor(m => m.Quantity)</td>
    <td>@Html.TextBoxFor(m => m.UnitPrice)</td>
    <td>
      <button type="button" class="delete" data-id="@Model.ProductID">Delete</button>
      @Html.HiddenFor(m => m.ProductID)
      @Html.HiddenFor(m => m.ProductName)
    </td>
  </tr>
}

Side notes:

  1. Do not include the hidden input for the Index
  2. An <input> is not a valid child of a <tr> element (place the hidden inputs inside a <td> element
  3. String.Format("{0}", Model.NorthOrderDetails[i].UnitPrice does absolutely nothing (If you wanted to to format it as (say) currency, then it would be @Html.TextBoxFor(m => m.UnitPrice. "{0:C}"))

You can now remove the for loop in the main view and replace with

<table id="Products" class="Products">
  <thead>
    <tr>
      <th>ProductId</th>
      <th>Productname</th>
      <th>Quantity</th>
      <th>UnitPrice</th>
    </tr>
  </thead>
  <tbody>
    @foreach(var item in Model.NorthOrderDetails)
    {
      @Html.Partial("_NorthOrderDetails", item)
    }
  </tbody>
</table>

This will generate a bit of extra html (the indexers for the existing items are a Guid rather than an int) but it means you only have one place to maintain your code.

Then in the main view, add the following script for your 'Add' button

<button type="button" id="add">Add</button>
<script>
  var tableBody = $('#Products tbody');
  var url = '@Url.Action("Add", "YourControllerName")'; // adjust to suit
  $('#add').click(function() {
    $.get('url, function(response) {
      tableBody.append(response);
    });
  });
</script>

And the controller method

public PartialViewResult Add()
{
  var model = new NorthOrderDetailscs();
  return PartialView("_NorthOrderDetails");
}

Finally, if you are using client side validation (jquery-validate-unobtrusive.js), and @Html.ValidationMessageFor() with your properties, then you need re-parse the validator each time you add new elements to the DOM as explained in this answer.