Самый простой способ сделать что-то подобное - использовать поддержку ASP.NET MVC для привязки модели к перечисляемой коллекции. По сути, когда вы создаете сотрудников для компании, они будут добавляться в список с использованием определенной структуры именования полей, которую связыватель моделей MVC может использовать для возврата списка элементов (Сотрудники).
public class Company
{
public string Name { get; set; }
public IEnumerable<Employee> Employees { get; set; }
}
public class Employee
{
public string EnglishName { get; set; }
public string JapaneseName { get; set; }
}
Company Name: <input type="text" name="Name" />
<!-- Employee 1 -->
English Name: <input type="text" name="Employees[0].EnglishName" />
Japanese Name: <input type="text" name="Employees[0].JapaneseName" />
<!-- Employee 2 -->
English Name: <input type="text" name="Employees[1].EnglishName" />
Japanese Name: <input type="text" name="Employees[1].JapaneseName" />
<!-- Employee 2 -->
English Name: <input type="text" name="Employees[2].EnglishName" />
Japanese Name: <input type="text" name="Employees[2].JapaneseName" />
В приведенном выше примере вы заметите, что для каждого поля сотрудника есть порядковый индекс для имени поля, это то, что сообщает ASP.NET MVC, что вы привязываетесь к списку и что каждый сотрудник [n] является отдельным объект должен быть привязан к модели. Важно, чтобы эти индексы оставались порядковыми, потому что если вы пропустите индекс, ваш список не будет привязан правильно.
Если все это сделано правильно, вы можете определить действие для обработки формы, которая получает объект Company в качестве параметра. MVC автоматически позаботится обо всем остальном.
В приведенном выше примере, конечно, предполагается статическое число сотрудников, что, скорее всего, никогда не будет иметь место, поэтому для повышения его гибкости мы можем использовать jQuery для создания новых строк для каждого сотрудника по мере их определения. Как я уже говорил, порядок индексации важен и должен оставаться последовательным.
Следующие обработчики кликов «Добавить и удалить» гарантируют, что при каждом создании нового сотрудника или удалении существующего в списке имена ваших полей будут оставаться порядковыми. Я извлек это из некоторого другого кода, который я написал, и немного изменил его для ваших целей. Я вполне уверен, что это поможет.
$('.add-employee').click(function() {
var nextIndex = 0;
var lastRow = $(this).siblings('.row:last');
if (lastRow.length > 0) {
var lastRegion = lastRow.find('input:last');
if (lastRegion.length > 0 && /\[(\d+)\]/.test(lastRegion.attr('name')) !== null) {
var key = lastRegion.parent().find('.key:text');
if (key.val() === '') {
key.focus();
return;
}
nextIndex = parseInt(/\[(\d+)\]/.exec(lastRegion.attr('name'))[1], 10) + 1;
}
}
var namePrefix = 'Employees[' + nextIndex + ']';
var newItem = '<div class="row">\n'
+ 'English Name: <input type="text" name="' + namePrefix + '.EnglishName" /><br />\n'
+ 'Japanese Name: <input type="text" name="' + namePrefix + '.JapaneseName" /> \n'
+ '<a href="#" class="remove-employee">Remove</a>\n'
+ '</div>';
$(this).before(newItem);
});
$('.remove-employee').live('click', function() {
var parent = $(this).parent();
parent.slideUp();
parent.nextAll('div').children(':text').each(function(index, element) {
element = $(element);
if (/\[(\d+)\]/.test(element.attr('name')) !== null) {
element.attr('name', element.attr('name').replace(/\[(\d+)\]/, '[' + (parseInt(/\[(\d+)\]/.exec(element.attr('name'))[1], 10) - 1) + ']'));
}
});
parent.remove();
return false;
});
Чтобы использовать эти обработчики кликов, вы должны определить ссылку / кнопку с именем класса «add-employee», а затем дополнительную ссылку / кнопку рядом с каждой записью сотрудника (в том же контейнере, что и поля для этого сотрудника) с именем « удалить-сотрудник». Обратите внимание на использование привязки live () в обработчике remove-employee, который гарантирует, что строки, добавляемые вами через первую функцию, будут иметь рабочие ссылки удаления.