2010-10-29 17 views
8

Korzystając z Entity Data Framework, mam zdefiniowany model o nazwie Client, który po prostu zawiera identyfikator i nazwę. Następnie mam powiązanie z innym modelem o nazwie Appointment zawierającym identyfikator i datę.ASP.NET MVC dynamicznie dodawaj rekordy podrzędne

Dla formularza, chciałbym umożliwić użytkownikom tworzenie nowego klienta i w tym samym formularzu, dodawać terminy (przed utworzeniem klienta). Częściowo działam (dodając jedno spotkanie).

W regulatorze:

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

W widoku:

<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()); %> 

'Partial' Widok:

<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> 

Jednak to nie jest idealny dla kilku powodów:

  1. Tylko jedno spotkanie można dodać
  2. Problemy pojawią się, jeśli wystąpią konflikty nazw (np. pole o nazwie Comments zarówno Client i Appointment tabeli), gdyż nie Prefiksacja odbywa się nazwy pól, co zapobiega również więcej niż jedno powołanie dodaje także

Co mogę zrobić, aby umożliwić wielu nominacje do dodania , czyli za pomocą przycisku, aby wyświetlić częściowy widok (przy użyciu AJAX prawdopodobnie) na stronie, gdy kliknięty zostanie "nowy termin", aby umożliwić jak największą liczbę spotkań? Chciałbym również, aby był to widok wspólny, który można wykorzystać zarówno do tworzenia i edytowania rekordów, jak i dodawania/usuwania spotkań w tej samej formie.

Aktualizacja
Pewien postęp, używając ViewModel:

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

Kontroler:

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(); 
    } 
} 

widoku (na spotkaniach, nie działa z foreach pętli, jak każdy z terminów są poprzedzone Appointment_ zamiast Appointment[0]_):

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

Jest to przydatne do tworzenia spotkań dla nowego klienta, ale co z ich edycją, a także dodawania nowych spotkań bez konieczności zwrotu formularza? Aby dodać, odsyłacz, który pokazuje nowy formularz spotkania pod istniejącym, z innym linkiem do usunięcia (ukryj przed widokiem i ustaw wartość ukrytego pola).

Aktualizacja 2
Got to praca, do dodawania terminów przy pierwszym tworzeniu klienta. Nie jestem jednak pewien, jak zaktualizować istniejące spotkania (nie usuwając wszystkich i dodając ponownie).

W sterowniku:

[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); 
} 

Widok:

<%= 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++; 
      } 
     ); 
}); 

Odpowiedz

1

Wystarczy kilka pomysłów pływających wokół ..

Jak około jeśli dokonać Wizycie częściowy widok zawierać formularz.

użyć jQuery/AJAX do obsługi przedstawienie postaci:

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

Które wysłać silnie wpisany Powołanie następującej metody działania:

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

Zasadniczo Twój przesyłającego formularz za pomocą AJAX, a następnie ponownie renderowanie wyniku z powrotem do częściowego. Wynik jest podobny do AJAX UpdatePanel (of WebForms fame).

Po wypełnieniu danych, naciśnięciu przycisku "prześlij", dane zostaną wysłane do kontrolera (przy użyciu AJAX), a następnie formularz będzie ponownie pusty, aby można było dodawać spotkania.

Czy to działa?

+0

Jedynym problemem jest to, że „klient” może nie mieć został już stworzony. Jeśli mogę poprzedzić nazwy pól słowem "Powołanie" i wprowadzić je w tablicy (tj. Dołączyć [] do nazwy), to czy nie byłoby to dziełem (używając UpdateModel ("Spotkanie", termin)? Chociaż nie wiem jak to ustawić w górę – SamWM

0

Istnieje kilka postów na blogu, które wyjaśniają, jak powiązanie modelu działa z listą złożonych elementów. Twoje podejście do modelu widoku powinno działać, gdy kiedykolwiek chcesz dodać nowe spotkanie, po prostu dodaj nowy element do listy spotkań (viewmodel) po stronie klienta z pewnym kodem JS.

przejść przez te linki, które wyjaśnia, w jaki sposób z pudełka MVC modelu wiążące będzie działać, jeśli uczynić html poprawnie

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

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

Powiązane problemy