Javascript 将项目动态添加到视图并发回控制器(ASP.NET MVC 4)

Javascript 将项目动态添加到视图并发回控制器(ASP.NET MVC 4),javascript,asp.net,asp.net-mvc,Javascript,Asp.net,Asp.net Mvc,我有一个带有模型的ASP.NET MVC 4应用程序,它包含和集合(IEnumerable或IList),即: classmymodel { 公共int Foo{get;set;} 公共IList条{get;set;} } 类项目 { 公共字符串Baz{get;set;} } 我用经典的@for…,@Html.EditorFor…广告等呈现视图中的数据。现在需要在客户端添加动态添加新项目,然后将其发布回服务器 我正在寻找一个简单的解决方案来处理添加(在JavaScript中),也就是不手动创建

我有一个带有模型的ASP.NET MVC 4应用程序,它包含和集合(
IEnumerable
IList
),即:

classmymodel
{
公共int Foo{get;set;}
公共IList条{get;set;}
}
类项目
{
公共字符串Baz{get;set;}
}
我用经典的
@for…
@Html.EditorFor…
广告等呈现视图中的数据。现在需要在客户端添加动态添加新项目,然后将其发布回服务器

我正在寻找一个简单的解决方案来处理添加(在JavaScript中),也就是不手动创建所有输入等,可能是为了从编辑器模板视图中获得它。另外,当表单提交回服务器时,模型绑定器将能够正确地创建
IList
集合,也就是对输入名称的一些智能处理。我读了很多文章,但没有一篇是容易且可靠的(没有像集合变量名、AJAX回调到服务器等神奇字符串)


到目前为止看起来很有希望,但我更愿意依赖于在服务器上呈现(预先知道的项目)

我是在主干网(用于文件上传)的帮助下完成这项工作的,每当用户单击#添加按钮时,我都会在主干网中插入模板 视图:

在控制器中保存代码


我希望这会有所帮助。

我不确定“集合变量名”是什么意思,也许我的解决方案有点神奇,你已经注意到了

我的解决方案基于复制元素的现有编辑器并通过Javascript更改输入名称

首先,我们需要给我们的编辑加分。这是一个用于集合的表单输出编辑器代码

        @for (var i = 0; i < Model.Count; i++)
        {
            <div class="contact-card">
                @Html.LabelFor(c => Model[i].FirstName, "First Name")
                @Html.TextBoxFor(c => Model[i].FirstName)
                <br />
                @Html.LabelFor(c => Model[i].LastName, "Last Name")
                @Html.TextBoxFor(c => Model[i].LastName)
                <br />
                @Html.LabelFor(c => Model[i].Email, "Email")
                @Html.TextBoxFor(c => Model[i].Email)
                <br />
                @Html.LabelFor(c => Model[i].Phone, "Phone")
                @Html.TextBoxFor(c => Model[i].Phone)
                <hr />
            </div>

        }

瞧!!提交后,我们将获得一个更多的元素

最后,我做了类似的事情,但是使用了集合的自定义(非线性)索引


这使用元素的手动命名(因此我不直接绑定到模型),并且可以使用自定义实例(对于空元素模板)。我还创建了一些helper方法来为实例生成代码,因此从模型或空实例更容易为实际实例生成代码。

如何处理集合最初是空的,并且没有“最后一个元素”?当您删除某些项目时,这是否有效?我认为索引必须从0开始连续。如果集合最初为空,则这不起作用。如果删除了某些项目,则该功能将正常工作。
@using Telerik.Web.Mvc.UI
@{
    ViewBag.Title = "FileUpload";
    Layout = "~/Areas/Administration/Views/Shared/_AdminLayout.cshtml";
}
<div id="fileViewContainer" class="span12">
<h2>File upload</h2>
@foreach(var fol in (List<string>)ViewBag.Folders){
        <span style="cursor: pointer;" class="uploadPath">@fol</span><br/>
    }
    @using (Html.BeginForm("FileUpload", "CentralAdmin", new { id = "FileUpload" }, FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <label for="file1">Path:</label>
        <input type="text" style="width:400px;" name="destinacionPath" id="destinacionPath"/><br />
        <div id="fileUploadContainer">
            <input type="button" class="addButton" id="addUpload" value="Add file"/>
            <input type="button" class="removeButton" id="removeUpload" value="Remove file"/>
        </div>

        <input type="submit" value="Upload" />
    }
</div>
<script type="text/template" id="uploadTMP">
     <p class="uploadp"><label for="file1">Filename:</label>
     <input type="file" name="files" id="files"/></p>
</script>
@{
    Html.Telerik().ScriptRegistrar().Scripts(c => c.Add("FileUploadInit.js"));
}
$(document).ready(function () {
    var appInit = new AppInit;
    Backbone.history.start();
});
window.FileUploadView = Backbone.View.extend({
    initialize: function () {
        _.bindAll(this, 'render', 'addUpload', 'removeUpload', 'selectPath');
        this.render();
    },
    render: function () {
        var tmp = _.template($("#uploadTMP").html(), {});
        $('#fileUploadContainer').prepend(tmp);
        return this;
    },
    events: {
        'click .addButton': 'addUpload',
        'click .removeButton': 'removeUpload',
        'click .uploadPath': 'selectPath'
    },
    addUpload: function (event) {
        this.render();
    },
    removeUpload: function (event) {
        $($('.uploadp')[0]).remove();
    },
    selectPath: function (event) {
        $('#destinacionPath').val($(event.target).html());
    }
});
var AppInit = Backbone.Router.extend({
    routes: {
        "": "defaultRoute"
    },
    defaultRoute: function (actions) {
        var fileView = new FileUploadView({ el: $("#fileViewContainer") });
    }
});
        @for (var i = 0; i < Model.Count; i++)
        {
            <div class="contact-card">
                @Html.LabelFor(c => Model[i].FirstName, "First Name")
                @Html.TextBoxFor(c => Model[i].FirstName)
                <br />
                @Html.LabelFor(c => Model[i].LastName, "Last Name")
                @Html.TextBoxFor(c => Model[i].LastName)
                <br />
                @Html.LabelFor(c => Model[i].Email, "Email")
                @Html.TextBoxFor(c => Model[i].Email)
                <br />
                @Html.LabelFor(c => Model[i].Phone, "Phone")
                @Html.TextBoxFor(c => Model[i].Phone)
                <hr />
            </div>

        }
var lastContent = $("#contact-form .contact-card").last().clone();
$("#contact-form .contact-card").last().after(lastContent);

$("#contact-form .contact-card")
    .last()
    .find("input")
    .each(function () {
        var currentName = $(this).attr("name");
        var regex = /\[([0-9])\]/;
        var newName = currentName.replace(regex, '[' + (parseInt(currentName.match(regex)[1]) + 1) + ']');
        $(this).val('');
        $(this).attr('name', newName);
    });