首页 > 解决方案 > Add textbox dynamically and post it to controller mvc

问题描述

I am new to mvc.for my application I have create collection in view. Lets say I have to display name and address first time. If user clicks copy it should clone the div of name and address. Even I clone it using Jquery it dosent textboxes. And I have to submit all the data back to controller.But it posting only first entry

I have created viewmodel and loop in view to display those in view. As index is 0 initially it is not displaying those text box. 

    public class Person
    {
        public string Name { get; set; }
        public string Address { get; set; }
    }
    public class PersonVM
    {
        public PersonVM()
        {
            Persons = new List<Person>();
        }
        public IList<Person> Persons { get; set; }
    }




    @model MvcApplication5.Models.PersonVM
@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<script src="~/Script/JavaScript.js"></script>
<div class="example-1">

    @using (Html.BeginForm("Create", "Person", FormMethod.Post, new { @id = "formpost", @class = "main-form" } ))
    {

        <div class="example-2">

            @for (int i = 0; i < Model.Persons.Count(); i++)
            {
                <p>Example one</p>
                <p>Example two</p>

                @Html.TextBoxFor(p => p.Persons[i].Name, null, new { @class = "form-control" })

                @Html.TextBoxFor(p => p.Persons[i].Address, null, new { @class = "form-control" })

            }

            <button type="button" class="btn-copy">Copy</button>

        </div>
        <input type="submit" id="submit" name="Submit" />

    }


</div>

<script>
    $(function () {
        $(".btn-copy").on('click', function () {
            var ele = $(this).closest('.example-2').clone(true);
            console.log(ele.find('input'));
            //var currentIndex = $(ele).split("[")[1][0];
            //var newIndex = Number(currentIndex) + 1;
            ele.find('input').each(function () {
                console.log($(ele));
                this.id = this.id.replace('0', '[' + 2 + ']');
                this.name = this.name.replace('[0]', '[' + 2 + ']');
                //$(ele).attr("name", $(ele).attr("name").replace(currentIndex, newIndex));
            });
            $(this).closest('.example-2').after(ele);
        });
        $(".main-form").on("submit", function () {
            //You might need to replace the selector here with something better and
            //repeat this for the name as well, or modify it to work with the whole div.
            //$.each($(".example-2"), function (index, inputContainer) {
            //    $.each($(inputContainer).children("div").children("input"), function (inputIndex, input) {
            //        var currentIndex = $(input).attr("name").split("[")[1][0];
            //        $(input).attr("name", $(input).attr("name").replace(currentIndex, index));
            //    });
            //});
            console.log($('.example-2').val);
        });
    });
</script>

标签: jqueryasp.net-mvc

解决方案


编辑:-我更仔细地查看了代码,并重新创建了它。我做了一些小的改动,但现在看起来是这样的。

//My Controller action methods
    public IActionResult Index()
    {
        var emptyModel = new PersonVM() {
            Persons = new List<Person>()
        };
        emptyModel.Persons.Add(new Person());
        return View(emptyModel);
    }

    [HttpPost]
    public IActionResult Index(PersonVM people)
    {
        return View(people);
    }

我没有对视图进行任何更改。但我已经把它都包括在这里了

@model PersonVM

<div class="example-1">

    @using (Html.BeginForm("Create", "Person", FormMethod.Post, new { @class = "main-form"}))
    {


        <div class="example-2">


            <div>

                @for (int i = 0; i < Model.Persons.Count(); i++)
                {
                    <p>Example one</p>
                    <p>Example two</p>

                    @Html.TextBoxFor(p => p.Persons[i].Name, null, new { @class = "form-control" })

                    @Html.TextBoxFor(p => p.Persons[i].Address, null, new { @class = "form-control" })

                }

                <button type="button" class="btn-copy">Copy</button>
            </div>
        </div>
        <input type="submit" name="Submit" />


    }


</div>
<script>
    $(function () {
        $(".btn-copy").on('click', function () {
            var ele = $(this).closest('.example-2').clone(true);
            $(this).closest('.example-2').after(ele);
        });
        $(".main-form").on("submit", function () {
            //You might need to replace the selector here with something better and
            //repeat this for the name as well, or modify it to work with the whole div.
            $.each($(".example-2"), function (index, inputContainer) {
                $.each($(inputContainer).children("div").children("input"), function (inputIndex, input) {
                    var currentIndex = $(input).attr("name").split("[")[1][0];
                    $(input).attr("name", $(input).attr("name").replace(currentIndex, index));
                });
            });
        });
    });
</script>

这是我提交的表格。 在此处输入图像描述

这是调试输出。 在此处输入图像描述

希望这能解决您的问题。一个问题是每次克隆时都必须清除 Person 名称和字段的值,但这很容易实现。

您会看到这一点,因为正在提交的所有文本框都具有相同的索引,并且当模型绑定发生时,每个新值都会覆盖现有值。你有两种方法可以解决这个问题。在您的点击监听器中分配新的索引,或者等到用户提交表单。以下是代码示例。

示例 - 1:在添加新文本框之前更新索引。

<script>
    //This assumes sequential indices.
    $(function () {
        $(".btn-copy").on('click', function () {
            var ele = $(this).closest('.example-2').clone(true);
            var currentIndex = $(ele).split("[")[1][0];
            var newIndex = Number(currentIndex) + 1;
            $(ele).attr("name", $(ele).attr("name").replace(currentIndex, newIndex);
            $(this).closest('.example-2').after(ele);
        })
    });
</script> 

示例 - 2:继续当前方法并在提交时应用索引。

<script>
    $(function () {
        $(".btn-copy").on('click', function () {
            var ele = $(this).closest('.example-2').clone(true);
            $(this).closest('.example-2').after(ele);
        });
        $("{selector for form}").on("submit", function() {
            //You might need to replace the selector here with something better and 
            //repeat this for the name as well, or modify it to work with the whole div.
            $.each("input[name='Persons[i].Address']", function(index, input){
                var currentIndex = $(input).split("[")[1][0];
                var newIndex = Number(currentIndex) + 1;
                $(input).attr("name", $(input).attr("name").replace(currentIndex, newIndex);                
            });
        });
    })


</script> 

推荐阅读