2016-06-21 15 views
5

Sfondo
Sto lavorando su progetto di sito web del cliente e ho utilizzato MVC per creare il sito. Ho EF che lavora con un SQLDB per memorizzare i dati.Crea elenco <T> alla vista e POST con modulo per MVC Controller

mio WebApp è dotato di una zona di back-office per la gestione/aggiunta/aggiornamento Item s ecc

una pagina particolare in questione consente all'utente di aggiungere un nuovo Item al database inserendo i dati e facendo clic ' Salva "nel modulo.

Il Item ha alcune proprietà che vengono tutte aggiunte al DB in una nuova riga.

Item contiene anche un List<Appointment> s dichiarato contro di esso (li serializzerò e li salverò nella colonna appropriata).

Gli oggetti appaiono così (Ho rimosso alcune proprietà per brevità):

public class Item 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public List<Appointment> Appointments { get; set; } 
    // Plus some other properties 
} 

public class Appointment 
{ 
    public string Day { get; set; } 
    public string From { get; set; } 
    public string To { get; set; } 
} 

Ho impostato un ViewModel da usare e sto praticando tutta quella roba al solito buone pratiche. Ecco come si presenta:

public class AddItemViewModel 
{ 
    [Required(ErrorMessage = "Please enter an item name")] 
    [Display(Name="Item Name")] 
    public string Name { get; set; } 

    [Display(Name="Appointments")] 
    public List<Appointment> Appointments { get; set; } 

    ... 
    // Other properties in here 
    ... 
} 

Sto usando il motore di visualizzazione Razor.

Ho tutto a posto usando l'helper @Html.EditorFor(x => x.Property); per tutti gli elementi (ma uno - vi dico in un attimo) sulle proprietà dell'oggetto root (Item).

Posso postare ViewModel sul controller e salvare un nuovo Item e tutto il jazz, quindi tutto va bene lì.

Problema
Ho un List<Appointment> dichiarato nel mio ViewModel.

Come posso consentire all'utente di aggiungere nuovi Appointment s per questo List<Appointment> da all'interno pagina?

voglio assegnarli all'oggetto Item da creare quando il ViewModel è pubblicato - Farò questo nel mio controller/servizi, ecc

Come posso raggiungere questo obiettivo?

vista desiderata
Ho bisogno che l'utente sia in grado di aggiungere Appointment s dall'interno della pagina - fino a tuttavia molti che piace, davvero.

Vorrei che ci fosse un elenco dei "creati" Appointment s in un elenco (ul o qualcosa di simile ecc.) In un'area nella pagina.

Sotto quella lista, vorrei qualche campo di testo che sono rilevanti per le proprietà Day, From e To per la Appointment - con un pulsante 'Aggiungi', che aggiunge alla lista (e cancella le caselle di testo, idealmente).

Come bonus, vorrei anche una sorta di pulsante "Elimina" × "-sque" accanto a ciascun elemento, per rimuoverlo dallo List<Appointment> e dalla vista.

Ecco un esempio (disegnato in MSPaint - strumenti della vecchia scuola ftw!) Di quello che immagino la vista a guardare come:

My desired view design

Le cose che ho provato
io siamo stati scavando in lungo e in largo, ma nulla è ancora arrivato in mio soccorso.

  • Ho guardato molte soluzioni a che fare con l'aggiunta di oggetti in JavaScript per pagina - che fa il lavoro. L'unico problema è che non posso prenderli nell'oggetto che viene pubblicato sul controller.

  • Sono stato anche indicato direttamente di utilizzare Ajax per creare un oggetto Appointment e inserirlo nella pagina, ma questo non sembra essere stato rilevato.

La tua esperienza, conoscenza e saggezza è molto apprezzata.

+0

Fare riferimento alle risposte [qui] (http://stackoverflow.com/questions/29161481/post-a-form-array-without- riuscito/29161796 # 29161796) e [qui] (http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) per alcune opzioni –

+0

Grazie @StephenMuecke - sembrerebbe che tu abbia avuto un po 'di esperienza con questo tipo di cose prima? Ho letto velocemente gli articoli che hai linkato - il secondo link sembra essere più rivolto a ciò che sto cercando. Avrò un aspetto corretto in modo più dettagliato quando il tempo lo consentirà. Nel frattempo, è possibile che tu possa essere in grado di fornirmi un codice di esempio per il mio scenario, per favore (capisco che potrebbe essere un * grande * chiedere, però)? –

+2

Dai un'occhiata a [questo DotNetFiddle] (https://dotnetfiddle.net/UjxtUW) per un esempio (e il tuo modello di 'appuntamento' dovrebbe essere 'DateTime Day',' TimeSpan From' e 'TimeSpan To' - not' string ') –

risposta

1
  1. Per essere in grado di aggiungere nuovi controlli appuntamenti di input nell'interfaccia utente in modo dinamico, il click del pulsante Aggiungi, è possibile

[codice qui sotto è dalla parte superiore della mia testa, e più come pseudo- codice]

a) utilizzare jQuery/js per clonare un div nascosto che è stato prestabilito nella vista che contiene tutti i controlli dell'appuntamento rilevanti.

ad es. questo sarebbe un pre-renderizzati div, che servirà da modello

<div style="display:none;" id="appointment-template"> 
    <input type=text> 
</div> 

E poi la funzione di clone di jQuery al clic di Add sarebbe qualcosa di simile

var addNewAppointmentRowFromTemplate = function(){ 
     $("#appointments-list-container").append($("#appointment-template").clone()); 
    } 

O

b) Get la vista parziale dal server e aggiungerla al form (sempre usando jQuery $ .get/js xhr)

$.get("controller/templatDivActionMethodUrl", function(data) { 
     $("#appointments-list-container").append(data); 
    }); 
  1. Per essere in grado di inviare il modello con List al punto che è accettato nel parametro Oggetto di ActionMethod, è possibile

a) dinamicamente creare un oggetto JSON utilizzando jQuery/javascript che ha la stessa struttura del server modello laterale (la manutenzione sarà un problema quando il modello viene modificato).

var appointmentsJson = []; 
    //foreach loop is a pseudo code, can be replaced with $.each() 
    foreach (var appointment in $("#appointments-list-container").children()){ 
      appointmentsJson.push(new {'day' : $(appointment).children("#day").val(),'from' : $(appointment).children("#from").val(),'to' : $(appointment).children("#to").val()}) ;} 

    //and then post this json to actionMethod 

    $.post("serverController/Actionmethod",{appointments: appointmentsJson}); 

O

b) Utilizzare la funzione ModelBinder che viene fornito con ASP.Net MVC.C'è una buona quantità di documentazione/tutorial su questo nostro lì, un punto di partenza: https://docs.asp.net/en/latest/mvc/models/model-binding.html

+0

Grazie per i tuoi suggerimenti. Avrò una giusta occhiata a loro con rabbia, quando avrò più tempo. Ho provato ad aggiungere viste parziali al modulo, prima. Sfortunatamente ModelBinder di MVC non ci riprenderebbe - qualcosa a che fare con l'indicizzazione? (come indicato nei link di @ stephen-muecke) - quindi mi rivolgo alle brave persone di SO per un po 'di aiuto –

+0

ok cool., ... sì un campo nascosto con un indice sequenziale è necessario affinché CustomModelBinder funzioni. –

+0

Ora che ho le idee chiare, ho rivisto la tua risposta. Esattamente a destra (che non stavo dubitando per un secondo). Il link https://dotnetfiddle.net/UjxtUW di @Stephen Muecke mi ha dato la spinta giusta nella giusta direzione, quindi gli ho chiesto di pubblicare una risposta - come vedo, è giusto. Se sceglie di non farlo, e puoi aggiungere un codice di esempio alla tua risposta (per i futuri arrivati ​​più di ogni altra cosa) - Prenderò in considerazione la possibilità di contrassegnarlo come accettato. Grazie ancora :) –