Add new row for new record to the end of table

2020-04-30 05:36发布

I have a table of data that I am rendering in a mass edit mode, so all rows are editable at once. The following code works great for editing existing data:

<table>
    <thead>
        <tr>
            <th>Row</th>
            <th>Parent</th>
        </tr>
    </thead>
    <tbody>
    @for (int i=0;i< Model.Config.Count;i++)
    {
    <tr>
        <td>
            @Html.HiddenFor(m => Model.Config[i].ConfigurationId)
            @Html.EditorFor(m=>Model.Config[i].RowNumber)
        </td>
        <td>
            @Html.EditorFor(m=>Model.Config[i].Parent)
        </td>
    </tr>
    }
    </tbody>
</table>
<input type="hidden" id="hNextConfigIndex" value="@Model.Config.Count" />

Since I'm using the for loop, Razor takes care of changing the names on all the elements that get rendered so that my model binds correctly to my controller.

I want to add a button to add a new record. I know that I can perform a post back to an action, add a blank record to the model, and then re-render the view with the updated model.

What I would like to do is perform this async using some JavaScript instead. My plan so far is to create an action that returns the rendered new row based on the last index (last index is stored in a hidden field, hNextConfigIndex).

Action

    public ActionResult GetNewRow(string rowType, int index)
    {
        ViewBag.RowType = rowType;
        ViewBag.Index = index;

        Document t = new Document();
        if (rowType == "Config")
        {
            t.Config = new List<Configuration>();
            t.Config.Add(new Configuration());
        }
        else if (rowType == ".....")
        {
        }

        return View("_NewRows", t);
    }

View

@model Data.Document

@{
    Layout = null;
}

@if (ViewBag.RowType=="Config")
{   
    for(int i=ViewBag.Index;i<=ViewBag.Index;i++)
    {
    <tr>
        <td>
            @Html.HiddenFor(m => Model.Config[i].ConfigurationId)
            @Html.EditorFor(m=>Model.Config[i].RowNumber)
        </td>
        <td>
            @Html.EditorFor(m=>Model.Config[i].Parent)
        </td>
    </tr>
  }
}

The action works, but the view of course does not. There is only a single blank dummy record, so of course the index i (where i > 0) is not going to exist.

I'm sure there are other ways of doing this. I could just copy the last row using javascript and change the values, but I would have to do a lot of hard coding in javascript that way.

1条回答
混吃等死
2楼-- · 2020-04-30 06:00

If jquery solution is acceptable, you can do it in client side. The below code might need refinement, but should give you an idea.

$("#btnAddConfig").click(function () {
    var template = $("#tblConfig > tbody tr").first().clone();
    var newIndex = $("#hNextConfigIndex").val();
    template.find("input").each(function () {
        var name = $(this).attr("name");
        var id = $(this).attr("id");

        name = name.replace(/\[\d+\]/g, "[" + newIndex + "]");
        id = id.replace(/\_\d+\__/g, "_" + newIndex + "__");

        $(this).attr("name", name);
        $(this).attr("id", id);
        $(this).val(""); //reset to defaults as applicable
    });
    $("#hNextConfigIndex").val(newIndex++);
    $("#tblConfig > tbody").append(template);
});

Fiddle

If you want to do it in server side, don't rebuild the entire table, but create an Action, say GetEditor for returning a tr with appropriate default values for the editor and then request it via ajax and append it to the table using jquery in the success handler.

Rebuilding the entire table just for adding a new record every time just adds to the load time as the records grow leaving the user to wonder why it take more and more time each time he adds a new record.

查看更多
登录 后发表回答