ASP.NET MVC динамически добавляет дочерние записи - PullRequest
9 голосов
/ 29 октября 2010

Используя Entity Data Framework, у меня есть определенная модель под названием Client, которая просто содержит идентификатор и имя. Затем у меня возникает ассоциация с другой моделью под названием Appointment, содержащей идентификатор и дату.

Для формы я хочу разрешить пользователям создавать нового клиента и в той же форме добавлять встречи (до создания клиента). У меня это частично работает (добавление одной встречи).

В контроллере:

[HttpPost]
public ActionResult Create(Client client)
{
    var appointment = new Appointment();
    UpdateModel(appointment);
    client.Appointments.Add(appointment);
    db.AddToClients(client);
    db.SaveChanges();
    return RedirectToAction("Index");
}

По виду:

<div class="editor-label">
    <%= Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
    <%= Html.TextBoxFor(model => model.Name) %>
    <%= Html.ValidationMessageFor(model => model.Name) %>
</div>
<% Html.RenderPartial("Appointment", new Appointment()); %>

'Частичное' представление:

<div class="editor-label">
    <%= Html.LabelFor(model => model.AppointmentDate) %>
</div>
<div class="editor-field">
    <%= Html.TextBoxFor(model => model.AppointmentDate) %>
    <%= Html.ValidationMessageFor(model => model.AppointmentDate) %>
</div>

Однако это не идеально по нескольким причинам:

  1. Можно добавить только одну встречу
  2. Проблемы возникнут, если возникнут какие-либо конфликты имен (например, поле с именем Comments в таблицах Client и Appointment), поскольку для имен полей не задан префикс, что также предотвращает более одного назначения также добавлено

Что можно сделать, чтобы разрешить добавление нескольких встреч, т. Е. Использовать кнопку для визуализации частичного представления (возможно, с использованием AJAX) на странице, когда нажимается «новая встреча», чтобы разрешить как можно больше встреч? Мне также хотелось бы, чтобы это было общее представление, которое можно использовать как для создания и редактирования записей, так и для добавления / удаления встреч в одной и той же форме.

Обновление
Некоторый прогресс, используя ViewModel:

public class ClientViewModel
{
    public Client Client { get; set; }
    public List<Appointment> Appointments { get; set; }
}

Контроллер:

public ActionResult Create()
{
    Client c = new Client();
    List<Appointment> appointments = new List<Appointment>();
    appointments.Add(new Appointment() { AppointmentDate = DateTime.Now });
    appointments.Add(new Appointment() { AppointmentDate = DateTime.Now.AddMonths(1) });

    var model = new ClientViewModel
    {
        Client = c,
        Appointments = appointments
    };
    return View(model);
}

[HttpPost]
public ActionResult Create(ClientViewModel m)
{
    try
    {
        foreach (var appointment in m.Appointments)
        {
            m.Client.Appointments.Add(appointment);
        }
        db.AddToClients(m.Client);

        db.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

Просмотр (для встреч не работает с циклом foreach, так как каждое из встреч имеет префикс Appointment_ вместо Appointment[0]_):

<%= Html.EditorFor(model => Model.Client) %>
<% for (int i = 0; i < Model.Appointments.Count(); i++) { %>
    <%= Html.EditorFor(model => Model.Appointments[i])%>
<% } %>

Это хорошо для создания встреч для нового клиента, но как насчет редактирования их, а также добавления новых встреч без отправки формы обратно? Для добавления - ссылка, которая показывает новую форму встречи под существующей, с другой ссылкой, которую нужно удалить (скрыть из вида и установить значение скрытого поля).

Обновление 2
Получил это, для добавления встреч при первом создании клиента. Однако я не уверен, как обновить существующие встречи (не просто удалив их все и добавив снова).

В контроллере:

[HttpPost]
public PartialViewResult AddAppointment(Appointment appointment, int index)
{
    List<Appointment> appointments = new List<Appointment>();
    for (int i = 0; i < index; i++)
    {
        appointments.Add(null);
    }
    appointments.Add(new Appointment() { AppointmentDate = DateTime.Now });
    ViewData["index"] = index;
    var model = new ClientViewModel
    {
        Appointments = appointments
    };
    return PartialView("Appointment", model);
}

Вид:

<%= Html.EditorFor(model => Model.Client) %>
<div id="appointments">
<% for (int i = 0; i < Model.Appointments.Count(); i++) { %>
    <%= Html.EditorFor(model => Model.Appointments[i]) %>
<% } %>
</div>
<a href="javascript:;" id="addappointment">Add Appointment</a>
<script type="text/javascript">
    var appIndex = <%= Model.Appointments.Count() %>;
    $("#addappointment").click(function () {
        $.post(
            "/Client/AddAppointment",
            {"index" : appIndex}, 
            function (result) {
                $("#appointments").append(result);
                // increase index by 1
                appIndex++;
            }
        );
});

Ответы [ 2 ]

2 голосов
/ 03 ноября 2010

Просто рассмотрим некоторые идеи ..

Как насчет того, чтобы сделать частичное представление Встреча , содержащее форму.

Используйте jQuery / AJAX для обработки отправки формы:

$.post(
   "/SomeController/AddAppointment",
        appointment, // grab this from the form
        function (result) { 
           $("#target").html(result); // this will be the div which contains the partial
        }
     );

, которая отправит строго типизированное Назначение следующему методу действия:

[HttpPost]
public PartialViewResult AddAppointment(Appointment appointment)
{
   // code to persist entity
   // code to add errors to model (if necessary)
   return PartialView("Appointment");
}

По сути, вы отправляете форму с использованием AJAX, а затем повторно выводите результат обратно в частичное.Результат аналогичен AJAX UpdatePanel (известности WebForms).

Таким образом, вы должны заполнить детали, нажать «отправить», детали будут отправлены на контроллер (с использованием AJAX), а затем форма будетоставьте поле пустым, чтобы вы могли продолжать добавлять встречи.

Будет ли это работать?

0 голосов
/ 23 октября 2013

Есть несколько постов в блоге, в которых объясняется, как привязка модели работает со списком сложных элементов.Подход модели представления должен работать, когда вы хотите добавить новую встречу, просто добавьте новый элемент в список встреч (viewmodel) на стороне клиента с некоторым JS-кодом.

Перейдите по этим ссылкам, где объясняется, как будет работать стандартная привязка модели MVC, если вы правильно отобразите HTML

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...