Ich weiß, dass XHTML keine verschachtelten Formular-Tags unterstützt, und ich habe hier auf Stack Overflow bereits andere Antworten zu diesem Thema gelesen, aber ich habe immer noch keine elegante Lösung für das Problem gefunden.
Einige sagen, dass Sie es nicht brauchen und dass sie sich kein Szenario vorstellen können, in dem dies erforderlich wäre. Ich persönlich kann mir kein Szenario vorstellen, das ich nicht gebraucht habe.
Sehen wir uns ein sehr einfaches Beispiel an:
Sie erstellen eine Blog-App und haben ein Formular mit einigen Feldern zum Erstellen eines neuen Beitrags und eine Symbolleiste mit "Aktionen" wie "Speichern", "Löschen", "Abbrechen".
<form
action="/post/dispatch/too_bad_the_action_url_is_in_the_form_tag_even_though_conceptually_every_submit_button_inside_it_may_need_to_post_to_a_diffent_distinct_url"
method="post">
<input type="text" name="foo" /> <!-- several of those here -->
<div id="toolbar">
<input type="submit" name="save" value="Save" />
<input type="submit" name="delete" value="Delete" />
<a href="/home/index">Cancel</a>
</div>
</form>
Unser Ziel ist es, das Formular so zu schreiben, dass kein JavaScript erforderlich ist , sondern nur ein altes HTML-Formular und Schaltflächen zum Senden.
Da die Aktions-URL im Formular-Tag und nicht in jeder einzelnen Senden-Schaltfläche definiert ist, besteht unsere einzige Option darin, auf einer generischen URL zu posten und dann "if ... then ... else" zu starten, um den Namen der Schaltfläche zu bestimmen, die diese Schaltfläche enthält wurde übermittelt. Nicht sehr elegant, aber unsere einzige Wahl, da wir uns nicht auf JavaScript verlassen wollen.
Das einzige Problem ist, dass durch Drücken von "Löschen" ALLE Formularfelder auf dem Server gesendet werden, obwohl für diese Aktion nur eine ausgeblendete Eingabe mit der Post-ID erforderlich ist. In diesem kleinen Beispiel keine große Sache, aber ich habe Formulare mit Hunderten (sozusagen) Feldern und Registerkarten in meinen LOB- Anwendungen, die (aufgrund von Anforderungen) alles auf einmal einreichen müssen, und dies scheint auf jeden Fall sehr ineffizient zu sein und eine Verschwendung. Wenn die Formularverschachtelung unterstützt würde, könnte ich zumindest die Schaltfläche "Löschen" in einem eigenen Formular nur mit dem Feld "Post-ID" umschließen.
Sie können sagen "Implementieren Sie einfach" Löschen "als Link anstatt zu senden". Dies wäre in so vielen Ebenen falsch, aber am wichtigsten ist, dass Nebenwirkungen wie "Löschen" hier niemals eine GET-Anforderung sein sollten.
Meine Frage (insbesondere an diejenigen, die sagen, dass sie keine Formverschachtelung benötigen) lautet: Was machen SIE? Gibt es eine elegante Lösung, die mir fehlt, oder lautet das Fazit wirklich "Entweder JavaScript benötigen oder alles einreichen"?
Antworten:
Ich würde dies genau so implementieren, wie Sie es beschrieben haben: Senden Sie alles an den Server und führen Sie ein einfaches if / else durch, um zu überprüfen, auf welche Schaltfläche geklickt wurde.
Und dann würde ich einen Javascript-Aufruf implementieren, der mit dem Onsubmit-Ereignis des Formulars verknüpft ist, das vor dem Senden des Formulars überprüft und nur die relevanten Daten an den Server sendet (möglicherweise über ein zweites Formular auf der Seite mit der ID, die für die Verarbeitung des Objekts erforderlich ist) eine versteckte Eingabe oder aktualisieren Sie den Seitenort mit den Daten, die Sie als GET-Anforderung übergeben müssen, oder senden Sie einen Ajax-Beitrag an den Server oder ...).
Auf diese Weise können Personen ohne Javascript das Formular problemlos verwenden, aber die Serverlast wird ausgeglichen, da die Personen mit Javascript nur die einzelnen benötigten Daten senden. Wenn Sie sich darauf konzentrieren, nur das eine oder andere zu unterstützen, werden Ihre Optionen unnötig eingeschränkt.
Wenn Sie alternativ hinter einer Unternehmensfirewall oder etwas anderem arbeiten und Javascript für alle deaktiviert ist, möchten Sie möglicherweise zwei Formulare erstellen und CSS-Magie anwenden, damit es so aussieht, als ob die Schaltfläche zum Löschen Teil des ersten Formulars ist.
quelle
Ich weiß, dass dies eine alte Frage ist, aber HTML5 bietet ein paar neue Optionen.
Die erste besteht darin, das Formular von der Symbolleiste im Markup zu trennen, ein weiteres Formular für die Löschaktion hinzuzufügen und die Schaltflächen in der Symbolleiste mithilfe des
form
Attributs ihren jeweiligen Formularen zuzuordnen.Diese Option ist recht flexibel, aber im ursprünglichen Beitrag wurde auch erwähnt, dass möglicherweise verschiedene Aktionen mit einem einzigen Formular ausgeführt werden müssen. HTML5 kommt wieder zur Rettung. Sie können das
formaction
Attribut für Senden-Schaltflächen verwenden, sodass verschiedene Schaltflächen im selben Formular an unterschiedliche URLs gesendet werden können. In diesem Beispiel wird der Symbolleiste außerhalb des Formulars lediglich eine Klonmethode hinzugefügt, die jedoch im Formular verschachtelt funktioniert.http://www.whatwg.org/specs/web-apps/current-work/#attributes-for-form-submission
Der Vorteil dieser neuen Funktionen ist, dass sie dies alles deklarativ ohne JavaScript tun. Der Nachteil ist, dass sie in älteren Browsern nicht unterstützt werden, sodass Sie für ältere Browser einige Polyfills durchführen müssen.
quelle
form=
bietet - sagt CanIUse nicht wirklich. caniuse.com/#feat=forms<input>
, Schaltflächen zu deklarieren. Zu<button>
diesem Zweck wurde das Element vor 15 Jahren eingeführt. Wirklich Leute.<input>
oder<button>
Elemente verwenden, spielt keine Rolle, obwohl Schaltflächen normalerweise eher für Symbolleisten geeignet sind, wie Sie sagen. Übrigens werden Schaltflächenelemente seit 15 Jahren nicht mehr von allen Browsern unterstützt.können Sie die Formulare nebeneinander auf der Seite haben, aber nicht verschachtelt. Verwenden Sie dann CSS, um alle Schaltflächen hübsch auszurichten?
quelle
HTML5 hat eine Idee von "Formularbesitzer" - dem Attribut "Formular" für Eingabeelemente. Es ermöglicht die Emulation verschachtelter Formulare und löst das Problem.
quelle
Ein altes Thema, aber dieses könnte für jemanden nützlich sein:
Wie oben erwähnt, können Sie Dummy-Formulare verwenden. Ich musste dieses Problem vor einiger Zeit überwinden. Zuerst habe ich diese HTML-Einschränkung völlig vergessen und nur die verschachtelten Formulare hinzugefügt. Ergebnis war interessant - ich habe meine erste Form aus dem verschachtelten verloren. Dann stellte sich heraus, dass es eine Art "Trick" war, einfach ein Dummy-Formular (das aus dem Browser entfernt wird) vor den tatsächlich verschachtelten Formularen hinzuzufügen.
In meinem Fall sieht es so aus:
Funktioniert gut mit Chrome, FireFox und Safari. IE bis 9 (nicht sicher über 10) und Opera erkennt keine Parameter im Hauptformular. Das globale $ _REQUEST ist unabhängig von den Eingaben leer. Innere Formen scheinen überall gut zu funktionieren.
Ich habe keinen anderen hier beschriebenen Vorschlag getestet - Feldsatz um verschachtelte Formulare.
EDIT : Frameset hat nicht funktioniert! Ich habe einfach das Hauptformular nach den anderen hinzugefügt (keine verschachtelten Formulare mehr) und den "Klon" von jQuery verwendet, um Eingaben im Formular beim Klicken auf die Schaltfläche zu duplizieren. .Hide () wurde zu jeder der geklonten Eingaben hinzugefügt, um das Layout unverändert zu lassen. Jetzt funktioniert es wie ein Zauber.
quelle
Ich denke, Jason hat recht. Wenn es sich bei Ihrer Aktion "Löschen" um eine minimale Aktion handelt, stellen Sie diese in einem eigenen Formular dar und richten Sie sie mit den anderen Schaltflächen aus, damit die Benutzeroberfläche wie ein einheitliches Formular aussieht, auch wenn dies nicht der Fall ist.
Oder gestalten Sie natürlich Ihre Benutzeroberfläche neu und lassen Sie die Benutzer an einer anderen Stelle vollständig löschen, ohne dass sie die enorme Form überhaupt sehen müssen.
quelle
Eine Möglichkeit, dies ohne Javascript zu tun, besteht darin, eine Reihe von Optionsfeldern hinzuzufügen, die die auszuführende Aktion definieren:
Dann würde das Aktionsskript abhängig vom Wert des Optionsfelds unterschiedliche Aktionen ausführen.
Eine andere Möglichkeit wäre, zwei Formulare wie vorgeschlagen auf die Seite zu setzen, nur nicht verschachtelt. Das Layout kann jedoch schwierig zu steuern sein:
Verwenden Sie das versteckte Feld "Aufgabe" im Bearbeitungsskript, um entsprechend zu verzweigen.
quelle
Diese Diskussion interessiert mich immer noch. Hinter dem ursprünglichen Beitrag stehen "Anforderungen", die das OP zu teilen scheint - dh ein Formular mit Abwärtskompatibilität. Als jemand, dessen Arbeit zum Zeitpunkt des Schreibens manchmal IE6 (und für die kommenden Jahre) unterstützen muss, grabe ich das.
Ohne das Framework voranzutreiben (alle Organisationen werden sich auf Kompatibilität / Robustheit verlassen wollen, und ich verwende diese Diskussion nicht als Rechtfertigung für das Framework), sind die Drupal-Lösungen für dieses Problem interessant. Drupal ist auch direkt relevant, da das Framework seit langem die Richtlinie "Es sollte ohne Javascript funktionieren (nur wenn Sie möchten)", dh das Problem des OP, verfolgt.
Drupal verwendet seine ziemlich umfangreichen form.inc- Funktionen, um das triggering_element zu finden (ja, das ist der Name im Code). Im unteren Bereich des auf der API-Seite aufgeführten Codes für form_builder (wenn Sie sich mit Details befassen möchten , wird die Quelle empfohlen - drupal-x.xx / includes / form.inc ). Der Builder verwendet die automatische HTML-Attributgenerierung und kann über diese bei der Rückkehr erkennen, welche Schaltfläche gedrückt wurde, und entsprechend handeln (diese können so eingerichtet werden, dass auch separate Prozesse ausgeführt werden).
Über den Formularersteller hinaus teilt Drupal die Aktionen zum Löschen von Daten in separate URLs / Formulare auf, wahrscheinlich aus den im ursprünglichen Beitrag genannten Gründen. Dies erfordert eine Art Such- / Auflistungsschritt ( stöhne ein anderes Formular!, Ist aber benutzerfreundlich) als Vorstufe. Dies hat jedoch den Vorteil, dass das Problem "Alles einreichen" beseitigt wird. Das große Formular mit den Daten wird für den beabsichtigten Zweck, die Datenerstellung / -aktualisierung (oder sogar eine Zusammenführungsaktion) verwendet.
Mit anderen Worten, eine Möglichkeit, das Problem zu umgehen, besteht darin, das Formular in zwei Teile zu teilen. Dann verschwindet das Problem (und die HTML-Methoden können auch über einen POST korrigiert werden).
quelle
Verwenden Sie ein
iframe
für das verschachtelte Formular. Wenn sie Felder gemeinsam nutzen müssen, dann ... ist es nicht wirklich verschachtelt.quelle
Meine Lösung besteht darin, dass die Schaltflächen JS-Funktionen aufrufen, die Formulare außerhalb des Hauptformulars schreiben und dann senden
quelle
Wenn Sie wirklich nicht mehrere Formulare verwenden möchten (wie Jason vorschlägt), verwenden Sie Schaltflächen und Onclick-Handler.
Und dann in Javascript (ich benutze jQuery hier aus Gründen der Einfachheit) (obwohl es ziemlich übertrieben ist, einige Onclick-Handler hinzuzufügen)
Ich weiß auch, dass dadurch die Hälfte der Seite ohne Javascript nicht funktioniert.
quelle
Als Antwort auf eine Frage, die Yar in einem Kommentar zu seiner eigenen Antwort gestellt hat, präsentiere ich JavaScript, mit dem die Größe eines Iframes geändert werden kann. Für den Fall einer Formularschaltfläche kann davon ausgegangen werden, dass sich der Iframe in derselben Domäne befindet. Dies ist der Code, den ich benutze. Sie müssen die Mathematik / Konstanten für Ihre eigene Site ändern:
Dann nenne es so:
quelle
Ich habe mir gerade eine nette Art ausgedacht, es mit jquery zu machen.
quelle
Wenn Sie ein Formular senden, sendet der Browser auch einen Namen und einen Wert für die Eingabe. Was Sie also tun können, ist
Auf der Serverseite suchen Sie einfach nach einem Parameter, der die Breitenzeichenfolge "action:" startet, und der Restteil gibt an, welche Aktion ausgeführt werden soll
Wenn Sie also auf die Schaltfläche Browser speichern klicken, erhalten Sie so etwas wie foo = asd & action: save = Save
quelle
Ich ging das Problem um, indem ich ein Kontrollkästchen einfügte, je nachdem, welche Form die Person tun wollte. Verwenden Sie dann 1 Schaltfläche, um das gesamte Formular zu senden.
quelle
Alternativ können Sie das Formular actiob on the fly zuweisen ... ist möglicherweise nicht die beste Lösung, entlastet aber sicher die serverseitige Logik ...
quelle