I have a ASP.NET MVC 4 app with model, that contains and colection (IEnumerable
or IList
), i.e.:
class MyModel
{
pu
I'm not sure what do you mean 'collection variable names' and probably my solution is kind of magic you noticed.
My solution is based on copying existing editor for element and altering input names via Javascript.
First of all, we need to mark up our editor. This is a code of form outputs editor for collection
@for (var i = 0; i < Model.Count; i++)
{
@Html.LabelFor(c => Model[i].FirstName, "First Name")
@Html.TextBoxFor(c => Model[i].FirstName)
@Html.LabelFor(c => Model[i].LastName, "Last Name")
@Html.TextBoxFor(c => Model[i].LastName)
@Html.LabelFor(c => Model[i].Email, "Email")
@Html.TextBoxFor(c => Model[i].Email)
@Html.LabelFor(c => Model[i].Phone, "Phone")
@Html.TextBoxFor(c => Model[i].Phone)
}
Our editor is placed into div with class contact-card
. On rendering, ASP.NET MVC gives names like [0].FirstName
, [0].LastName
... [22].FirstName
, [22].LastName
to inputs used as property editors. On submitting Model Binder converts this to collection of entities based both on indexes and property names.
Next we create javascript function that copies last editor and increases index in brackets by 1. On submitting it adds additional element to collection:
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);
});
VOILA!! On submitting we will get one more element!