As Klors indicated, create a view models for Address and Person (suggest List<AddressVM>
is initialized in PersonVM
constructor). In your PersonController
[HttpGet]
public ActionResult Create()
{
PersonVM model = new PersonVM();
model.Addresses.Add(new AddressVM()); // add an empty address assuming at least one required
return View(model, "Edit")
}
[HttpGet]
public ActionResult Edit(int ID)
{
PersonVM model = // get from database/repository
// If Address.Count == 0, add new Address
return View(model);
}
[HttpPost]
public ActionResult Edit(PersonVM model)
{
...
In your view
@model PersonVM
@using (Html.BeginForm("Edit", "Person") {
....
@Html.HiddenFor(m => m.ID)
@Html.TextBoxFor(m => m.Name)
...
@Html.EditorFor(m => m.Addresses) // you may want to create an editor template for AddressVM
<button type="button" id="AddAddress">Add address</button>
The EditorFor()
will generate HTML similar to this (note the indexer)
<input type="text" name="Address[0].Street" id="Address_0__Street" ..../>
<input type="text" name="Address[0].Suburb" id="Address_0__Suburb" ..../>
To dynamically add new addresses, you need to use JavaScript to generate similar HTML, but increment the indexer. If you use an editor template, you can wrap the Address
controls in a container (say <div class="address">
) which make them easy to select as per the script below
Script to dynamically add a new address
$('#AddAddress').click(function() {
var addresses = $('.address');
// Get the number of existing address
var count = addresses.length;
// Get the first address and clone it
var clone = addresses.first().clone();
// Update the index of the clone
clone.html($(clone).html().replace(/\[0\]/g, '[' + count + ']'));
clone.html($(clone).html().replace(/"_0__"/g, '_' + count + '__'));
// Add to the DOM
addresses.last().after(clone);
}
Note this will also clone the values from the first address, so you may want to reset some or all of them, for example (after its been added)
clone.find('input').val('');
If you're using @Html.ValidationMessageFor()
methods, note that dynamically added elements will not be validated in the browser unless you parse the form. An example of how to do that can be found here: jquery.validate.unobtrusive not working with dynamic injected elements