2010-12-27 10 views
12

Ho un'applicazione Web, costituita principalmente da un grande modulo con informazioni. Il modulo è suddiviso in più schede, per renderlo più leggibile per l'utente:Il modo migliore per aggiungere un modulo aggiuntivo (nidificato) nel mezzo di un modulo a schede

<form> 
<div id="tabs"> 
    <ul> 
    <li><a href="#tab1">Tab1</a></li> 
    <li><a href="#tab2">Tab2</a></li> 
    </ul> 
    <div id="tab1">A big table with a lot of input rows</div> 
    <div id="tab2">A big table with a lot of input rows</div> 
</div> 
</form> 

Il modulo viene dinamicamente esteso (righe in più vengono aggiunti alle tabelle). Ogni 10 secondi il modulo viene serializzato e sincronizzato con il server.

Ora desidero aggiungere un modulo interattivo su una delle schede: quando un utente immette un nome in un campo, questa informazione viene inviata al server e viene restituito un ID associato a tale nome. Questo ID viene utilizzato come identificatore per alcuni campi modulo aggiunti dinamicamente.

Un rapido SketchUp di tale pagina sarebbe simile a questa:

<form action="bigform.php"> 
<div id="tabs"> 
    <ul> 
    <li><a href="#tab1">Tab1</a></li> 
    <li><a href="#tab2">Tab2</a></li> 
    </ul> 
    <div id="tab1">A big table with a lot of input rows</div> 
    <div id="tab2"> 
    <div class="associatedinfo"> 
    <p>Information for Joe</p> 
    <ul> 
     <li><input name="associated[26][]" /></li> 
     <li><input name="associated[26][]" /></li> 
    </ul> 
    </div> 

    <div class="associatedinfo"> 
    <p>Information for Jill</p> 
    <ul> 
     <li><input name="associated[12][]" /></li> 
     <li><input name="associated[12][]" /></li> 
    </ul> 
    </div> 
    <div id="newperson"> 
     <form action="newform.php"> 
     <p>Add another person:</p> 
     <input name="extra" /><input type="submit" value="Add" /> 
     </form> 
    </div> 
    </div> 
</div> 
</form> 

È possibile che questo non funziona: forme nidificati non sono ammessi in HTML. Tuttavia, ho davvero bisogno di visualizzare il modulo in quella scheda: fa parte della funzionalità di quella pagina. Voglio anche il comportamento di un modulo separato: quando l'utente raggiunge il ritorno nel campo modulo, viene premuto il pulsante di invio "Aggiungi" e viene attivata un'azione di invio sul modulo parziale.

Qual è il modo migliore per risolvere questo problema?

+1

utilizza una forma grande con più pulsanti. ogni pulsante può avere un valore diverso, ovvero il modo in cui il codice back-end può indicare quale pulsante è stato effettivamente inviato per inviare il modulo. il tuo codice di back end può quindi fare cose diverse a seconda del pulsante che è stato premuto. oppure puoi anche fare in modo che il pulsante "sotto forma" chiami AJAX invece di inviare il modulo, che ti consente di interrogare il server e ottenere una risposta senza aggiornare la pagina. è quindi possibile utilizzare javascript per utilizzare la risposta alla query AJAX per creare i campi modulo aggiuntivi. – dqhendricks

risposta

10

Una cosa che si potrebbe fare è invece di impostare il tipo di elemento di input "Add" a "presentare", impostarlo su "bottone" e aggiungere un attributo id per la registrazione di un gestore di clic:

<!-- ... --> 
    <div id="newperson"> 
     <p>Add another person:</p> 
     <input id="extra_input" name="extra" /><input id="add_button" type="button" value="Add" /> 
    </div> 
<!-- ... --> 

il motivo per il tipo di ingresso "pulsante" è che il pulsante risultante sulla pagina appare esattamente come un pulsante di invio, ma non fa nulla per impostazione predefinita quando si fa clic, permettendoti di personalizzare il suo effetto. Inoltre, il tipo di input "pulsante" è supportato in tutti i browser che supportano l'HTML 3.2 o successivo including HTML 5.

Da qualche parte nel tuo Javascript probabilmente hai una funzione che desideri venga chiamata ogni volta che l'utente fa clic sul pulsante "Aggiungi". Supponendo che si chiama addAnotherPerson, è sufficiente chiamare addAnotherPerson all'interno di un gestore di clic:

// This is jQuery code, but all JS frameworks that I have seen have a similar feature to register a click handler on a DOM element referenced by ID. 
$("#add_button").click(function (event) { 
    addAnotherPerson(); 
    $("#extra_input").val(""); // reset the value 
}); 

È inoltre necessario aggiungere un gestore keydown al metodo di scrittura "extra" per eseguire la stessa azione quando l'utente preme verso il basso la Enter chiave:

$("#extra_input").keydown(function (event) { 
    if (event.keyCode == 0xa || event.keyCode == 0xd) { 
     addAnotherPerson(); 
     $("#extra_input").val(""); // reset the value 
    } 
}); 

assicurarsi di aggiungere l'attributo autocomplete="off" al metodo di scrittura "extra".

La funzione addAnotherPerson potrebbe inviare una richiesta POST asincrona contenente il valore nella casella di testo "extra", aggiornando successivamente il DOM, se appropriato.

EDIT: Se anche voi volete supportare gli utenti che hanno JavaScript disabilitato, poi con l'aggiunta di name attributi ad ogni pulsante di invio con un unico valore di attributo name per ciascuno, l'applicazione lato server sarà in grado di dire quale pulsante che l'utente ha fatto clic.

Prendiamo, per esempio, questo codice da http://www.alanflavell.org.uk/www/trysub.html:

<table> 
<tr><td align=left><label for="aquavit_button"><input id="aquavit_button" type="submit" name="aquavit" value="[O]"> Aquavit</label></td></tr> 
<tr><td align=left><label for="beer_button"><input id="beer_button" type="submit" name="beer" value="[O]"> Beer</label></td></tr> 
<tr><td align=left><label for="champagne_button"><input id="champagne_button" type="submit" name="champagne" value="[O]"> Champagne</label></td></tr> 
<tr><td align=left><label for="water_button"><input id="water_button" type="submit" name="water" value="[O]"> Dihydrogen monoxide</label></td></tr> 
</table> 

Se l'utente fa clic sul pulsante "[O]" accanto a "Birra", quindi il browser invia una variabile POST "birra", ma non una variabile POST "acquavite", "champagne" o "acqua". Provalo allo http://www.alanflavell.org.uk/www/trysub.html.

Un problema complesso con questa tecnica è il caso in cui l'utente invia il modulo premendo il tasto Invio all'interno di un input di testo. Firefox invia una variabile POST per il primo pulsante di invio nel modulo ("aquavit" in questo caso) mentre Internet Explorer non invia una variabile POST per nessuno dei pulsanti di invio. È possibile assegnare più di questa differenza con l'aggiunta di un nascosto, senza nome pulsante di invio al proprio all'inizio della forma:

<form action="bigform.php"><input type="submit" style="display:none;" /> 
<!-- ... --> 

EDIT2: Se fate sempre in modo che il valore nel immissione di testo "extra" viene cancellato da Javascript prima che venga inviato il modulo grande, sarete in grado di dire se l'utente ha Javascript disabilitato e premono il tasto Invio nell'input di testo "extra" (che indica che vogliono l'azione add-a-person per run) controllando se la variabile "extra" POST non è vuota sul lato server. Se non è vuoto, allora puoi presumere che l'utente abbia Javascript disabilitato e che voglia aggiungere una persona.

Aggiungere questo codice:

$("#bigform").submit(function (event) { 
    $("#extra_input").val(""); // reset the value in the "extra" text input 
    return true; 
}); 
0

È possibile utilizzare ajax o creare l'altro modulo al di fuori del primo e posizionarlo utilizzando il livello DIV assoluto.

È facile leggere la posizione del livello utilizzando javascript. Innanzitutto creerai un segnaposto con altezza predefinita, quindi potrai visualizzare il modulo sopra il segnaposto.

<form> 

... 
    <div style='height: 300px;' class='placeholder'> ... </div> 
</form> 

<form>...<form> 

È possibile visualizzare la seconda forma in cui è .placeholder

+5

Questo rovinerà il "flusso" del modulo: voglio essere in grado di sfogliarlo usando solo la tastiera. Posso risolvere questo problema impostando un carico di tabindex, ma il contenuto dinamico rende questo un sacco di contabilità. – Scharrels

+0

Bene, questa è l'unica opzione se si desidera avere un comportamento del modulo exac. Altrimenti basta rilasciare il tag FORM nidificato e fare tutto usando AJAX. Ed è possibile impostare facilmente il tabindex sul client utilizzando una semplice funzione Ajax. – Slawek

1

Perché non nidificano gli oggetti modulo e gestire tutte le azioni in codice di PHP ...

# have this form appended to the DOM via ajax/js when a link is clicked 
<div id="newperson"> 
    <p>Add another person:</p> 
    <input type="text" name="associated[new][]" /> 
</div> 

Poi usare la logica php sul backend per creare l'associazione se è "nuovo":

foreach($_POST['associated'] as $obj) { 
    if($obj == "new") 
    // create a new record 
    else 
    // do your other processing 
} 
1

È possibile spostare il modulo di aggiunta al di fuori del modulo padre e nascondere usando CSS, quindi, come un altro poster ha detto, sostituisci il pulsante di invio per il modulo di aggiunta con un pulsante con un ID corretto, e infine, aggancia sia onkeypress sull'input, sia onclick sul pulsante per simulare una sottomissione dell'attuale aggiungi modulo.

<form action="bigform.php"> 

    .... 

    <div id="newperson"> 
     <p>Add another person:</p> 
     <input name="extra" /><button value="Add"/> 
    </div> 
    </div> 
</div> 
</form> 
<div style='display:none;'> 
    <form action="newform.php" id='add_person_form'> 
     <input id='add_person_name' /> 
     <input type="submit" id='add_person_submit' /> 
    </form> 
</div> 

<script> 
$('#newperson input').keyup(function(e) { 
    if(e.keyCode == 13) submitNewPersonForm(); 
}); 
$('#newperson button').click(function(e) { 
    submitNewPersonForm(); 
}); 

function submitNewPersonForm() { 
    // copy the content from the placeholder form 
    $('#add_person_name').val($("#newperson input").val()); 
    // submit this form 
    $("#add_person_form").submit(); 
} 
</script> 

Questo dovrebbe fare tutto il necessario mantenendo la funzionalità originale, per quanto posso dire.

Nota: il pulsante di invio non è realmente necessario sul modulo #add_person_form, l'ho appena tenuto lì in modo da poter facilmente vedere dove ho spostato il modulo.

2

Qualcosa come il seguente dovrebbe farlo.

Se JavaScript è disabilitato è necessario rilevare se l'utente preme il "Aggiungi" submitButton con:

$_POST["submitButton"] == "Add" 


    <!-- other stuff goes here --> 

    <div id="newperson"> 
     <p>Add another person:</p> 
     <input name="extra" id="extra" /><input name="submitButton" id="addPerson" type="submit" value="Add" /> 
    </div> 
    </div> 
</div> 
</form> 
<script> 
    var extra = $("#extra"), 
     addPerson = $("#addPerson").click(function(e){ 
     // val would be the new person's name, e.g., "David" 
     var val = extra.val(); 
     // you will want to give the user some AJAXy feedback here. 

     $.post(this.form.action, {"extra": val}, function(response){ 
      // rest the extra div. 
      extra.val(""); 

      /* 'response' could look like:        */ 
      // <div class="associatedinfo"> 
      //  <p>Information for David</p> 
      //  <ul> 
      //  <li><input name="associated[13][]" /></li> 
      //  <li><input name="associated[13][]" /></li> 
      //  </ul> 
      // </div> 
      $(response).insertBefore("#newperson"); 

      // or 'response' could be json data, or whatever. I have a feeling 
      // you know enough about jQuery to handle the response-data. :-) 

     }); 
     // prevent it from bubbling up. 
     e.preventDefault(); 
    }); 

    extra.keydown(function(e){ 
     // submit the new person's name via ajax if enter is pressed. 
     if(e.keyCode === 13){ 
      addPerson.click(); 
      e.preventDefault(); 
     } 
    }); 
</script> 
+1

'$ (" # extra ")' funziona solo quando il DOM è pronto. È necessario avvolgere lo script all'interno di '$ (function() {' e '});' o della sintassi equivalente '$ (document) .ready (function() {...});'. –

+0

@Daniel Trebbien. No, non lo fai. Tutti i browser di classe A possono attivare questo codice correttamente. Leggi [questo] (https://groups.google.com/group/closure-library-discuss/browse_thread/thread/1beecbb5d6afcb41?pli=1) per maggiori informazioni sui motivi per cui Closure Library non ha nemmeno un evento dom-ready . –

+0

Interessante. Il link che hai fornito suggerisce che il tuo codice funzioni se inserisci lo script * dopo * gli elementi DOM che lo script richiede per essere pronto. Ma se hai messo l'elemento 'script' in' head' (sì, lo so che è cattivo, ma è comune) o da qualche parte prima, allora dovrebbe essere racchiuso tra '$ (function() {' e '}), giusto? Questa tecnica DOM-bypass-bypass funziona in IE 6? –

6

HTML dovrebbe essere semantica, e dovrebbe essere considerato prima - vale a dire che dovrebbe avere un struttura chiara e significato senza una comprensione di ciò che javascript si trova in cima. Come il modo in cui uno <ul> deve contenere solo elementi <li>, uno <form> dovrebbe avere un solo scopo. L'uso di javascript per migliorare un modulo recuperando dati dinamici va bene, ma se si utilizza un POST HTTP aggiuntivo (il tipo che modifica i dati sul server), questo rappresenta davvero un secondo scopo, e quindi dovrebbe essere usato un secondo modulo . Una seconda forma, con il suo attributo "azione", segnala che un comportamento distinto sta accadendo qui, e non è solo più concettualmente sano, ma più facile da analizzare, eseguire il debug o estendere quando necessario.

<form id="bigform" action="bigform.php"> 
    <!-- Tabs here --> 
</form> 
<form id="newperson" action="newform.php"> 
    <input name="extra"> 
    <button type="submit" value="Add"> 
    <!-- Note also the use of <button> instead of <input> --> 
</form> 

La cosa importante è che è ancora possibile ottenere il flusso desiderato all'interno del modulo principale. Nel modulo principale, anziché utilizzare un modulo annidato, utilizzare <fieldset>. Questo fieldset si comporterà come proxy per il modulo newperson. L'input qui dentro può avere un ID, ma non dovrebbe avere un nome dato che il suo valore non deve essere inviato con il modulo principale. Come già menzionato in altre risposte, il pulsante dovrebbe essere cambiato in un tipo di "pulsante" e non in "invio".

<form id="bigform" action="bigform.php"> 
    <!-- Tabs here --> 
    <fieldset id="newpersonProxy"> 
     <input id="extra"> 
     <button type="button" value="Add"> 
    </fieldset> 
</form> 

Ora aggiungere il comportamento desiderato discretamente attraverso Javascript, da:

  1. Nascondere la seconda forma, #newperson.
  2. Risposta a "invia" legandosi all'evento keyup di qualsiasi input all'interno di #newpersonProxy, nonché all'evento click del pulsante. Per l'evento keyup, utilizzare event.which anziché event.keyCode poiché jQuery lo normalizza. Si desidera event.which == 13 per la chiave di invio.
  3. Quindi copiare il valore dagli input proxy sul modulo reale, prima di chiamare $("#newperson").submit().

In questo modo viene delegata la responsabilità di serializzare e inviare i dati al secondo modulo, consentendo di collegare qualsiasi tipo di logica al secondo modulo e di essere disaccoppiato dal primo.

Inoltre, poiché l'HTML funzionante è stato considerato per primo, un semplice tweak può consentire ai moduli di funzionare perfettamente senza Javascript - è sufficiente nascondere lo <fieldset> tramite CSS e mostrarlo con Javascript. Se Javascript è disattivato, le schede si romperanno, il fieldset nidificato verrà nascosto e verrà visualizzato il secondo modulo (e completamente funzionante, non solo tramite AJAX).

2

Questo non è affatto dettagliato come le altre risposte, ma ..

Dovrebbe essere super facile;)

  • sbarazzarsi del vostro tag FORM completamente
  • utilizzare jQuery per ottenere campo di inserimento valori
  • Quando un utente fa clic sul presentare "un" elemento che sembra un pulsante di invio, effettua semplicemente una richiesta Ajax, acquisendo i valori dei campi di input.

Ecco un example che mostra un po ' della formattazione sto riferimento, tuttavia questo mantiene i tag di modulo ed è un vecchio esempio da quando ho usato la biblioteca Scriptaculous. Ecco the JS, dimostra un po 'della strutturazione.

Se mi +1 e fammi sapere u come questa risposta, ho svilupperà un esempio funzionale per voi;)

Cheers! Kirk

1

Il modo in cui ho visto scenari simili gestiti è quello di creare una pagina modale per il modulo "interno", quindi non è richiesto alcun nidificazione. Non vedo questo metodo ostacolare in modo significativo il flusso della pagina.

In caso contrario, gli altri suggerimenti per inviare il modulo "interno" o l'intero modulo tramite AJAX possono funzionare anche.

1

Non è necessario un modulo nidificato, è possibile utilizzare un altro modulo (non nidificato) e utilizzare il posizionamento assoluto per posizionarlo in qualsiasi punto della pagina..quasi tutta questa creazione di controlli dinamici con ID correlati al nome immesso dagli utenti sembra molto complicato ... potremmo avere una soluzione più semplice se potessi condividere il problema commerciale che potresti provare a risolvere.

Problemi correlati