2

I have 3 controls(one textbox, one numericbox and a date) inside a view form, these 3 forms the Model object. There is link provided to the user, on click of this link all the 3 controls were repeated 5 times inside the form.

I have a list of Model class as an argument type in the controller action method. How to clone the form content 5 times such that it serializes properly to List?

DivideByzero
  • 474
  • 4
  • 15
  • In your Razor view use a `@for()` loop with a counter. Show us what you have attempted. – Jasen Dec 11 '15 at 18:48
  • Refer answers [here](http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796) and [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) for some options –  Dec 11 '15 at 20:32

2 Answers2

4

A simpler way.

Model :

public class MyModel
{
    public IList<OneSetOfElements> FormSet { get; set; }
}

public class OneSetOfElements
{
    public string Name { get; set; }
    public int Age { get; set; }

    [DataType(DataType.Date)]
    public DateTime Dob { get; set; }
}

Action :

public ActionResult MyAction(MyModel model)
{
    foreach (var set in model.FormSet)
    {
        //read your data.
    }
}

View : Show the id "showMeOnUrlClick" on click

    @using (Html.BeginForm())
    {

//This would bind as first list element
        <div id="firstSet"> 
            @Html.EditorFor(m => m.FormSet[1].Name)
            @Html.EditorFor(m => m.FormSet[1].Age)
            @Html.EditorFor(m => m.FormSet[1].Dob, new { type = "date" })

        </div>

//Remaining list element
        <div id="showMeOnUrlClick" style="display: none"> 
            @for (int i = 1; i <= 6; i++)
            {
                @Html.EditorFor(m => m.FormSet[i].Name)
                @Html.EditorFor(m => m.FormSet[i].Age)
                @Html.EditorFor(m => m.FormSet[i].Dob, new {type = "date"})
            }
        </div>

        <button onclick="showTheRepeatedFields() ">Show</button>
    }
2

You should use jQuery to dynamically create a row with all the 3 input fields when user clicks on the Add button.

So in your razor view (ex:Create), create the first row with the three form fields.

@using (Html.BeginForm())
{
   <a href="#" id="addRow">Add</a>
   <div id="items">
      <div class="itemRow">
         <label>Name</label> <input type="text" class="formfield" name="Name" />
         <label>Age</label>  <input type="text" class="formfield" name="Age" />
         <label>CreateDate</label><input type="text" class="formfield" name="CreateDate" />
      </div>
   </div>
    <input type="submit" id="btnSubmit" />
}

Now we will add some client side code to listen to the click event on the Add link, create a clone of the container div(with css class itemRow) and append it to the outer container div(with id items). When user clicks the submit button, we will read the form fields and build an array of object and post that to the server using jQuery ajax.

@section Scripts
{
<script type="text/javascript">

    $(function () {

        $("#addRow").click(function (e) {
            e.preventDefault();    
            var template = $("#items").find(".itemRow").first();
            var newRow = template.clone();
            newRow.find("input.formfield").val("");
            $("#items").append(newRow);

        });

        $("#btnSubmit").click(function (e) {
            e.preventDefault();
            var _this = $(this);
            var url =_this.closest("form").attr("action");

            var rows = [];
            var items = $(".itemRow");

            $.each(items, function (i, item) {                   
                var name =  $(item).find("input[name='Name']").val();
                var age =  $(item).find("input[name='Age']").val();
                var createDt =  $(item).find("input[name='CreateDate']").val();

                var row = { Name: name, Age: age, CreateDate: createDt };
                rows.push(row);    
            });

            //Let's post to server
            $.ajax({
                type:"POST",
                url: url,
                data: JSON.stringify(rows),
                contentType: "application/json"                       
            })
            .done(function (result) {
                //do something with the result
            })                 

        });    
    });    
</script>
}

Now you need an HttpPost action method to handle your form posting.

[HttpPost]
public ActionResult Create(IEnumerable<CreateUser> model)
{
    foreach(var item in model)
    {
        // to do  :Save
    }
    return Json( new { status ="success"});
}

and your CreateUser view model will look like

public class CreateUser
{
    public string Name { set;get;}
    public int Age { set; get; }
    public DateTime CreateDate { set; get; }
}
Shyju
  • 214,206
  • 104
  • 411
  • 497