Sé que XHTML no admite etiquetas de formulario anidadas y ya he leído otras respuestas aquí en Stack Overflow con respecto a este tema, pero aún no he encontrado una solución elegante para el problema.
Algunos dicen que no lo necesita y que no pueden pensar en un escenario en el que esto sería necesario. Bueno, personalmente no puedo pensar en un escenario en el que no lo haya necesitado.
Veamos un ejemplo muy simple:
Está creando una aplicación de blog y tiene un formulario con algunos campos para crear una nueva publicación y una barra de herramientas con "acciones" como "Guardar", "Eliminar", "Cancelar".
<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>
Nuestro objetivo es escribir el formulario de una manera que no requiera JavaScript , simplemente un formulario HTML antiguo y botones de envío.
Dado que la URL de acción se define en la etiqueta del formulario y no en cada botón de envío individual, nuestra única opción es publicar en una URL genérica y luego comenzar "if ... then ... else" para determinar el nombre del botón que fué enviado. No es muy elegante, pero es nuestra única opción, ya que no queremos confiar en JavaScript.
El único problema es que al presionar "Eliminar", se enviarán TODOS los campos del formulario en el servidor, aunque lo único que se necesita para esta acción es una entrada oculta con la identificación posterior. No es gran cosa en este pequeño ejemplo, pero tengo formularios con cientos (por así decirlo) de campos y pestañas en mis aplicaciones LOB que (debido a los requisitos) tienen que enviar todo de una vez y, en cualquier caso, esto parece muy ineficiente y un desperdicio. Si se admitiera la anidación de formularios, al menos sería capaz de ajustar el botón de envío "Eliminar" dentro de su propio formulario con solo el campo post-id.
Puede decir "Simplemente implemente" Eliminar "como un enlace en lugar de enviar". Esto sería incorrecto en muchos niveles, pero lo más importante es que las acciones de efectos secundarios como "Eliminar" aquí, nunca deberían ser una solicitud GET.
Entonces mi pregunta (particularmente para aquellos que dicen que no han necesitado anidar) es ¿Qué haces TÚ? ¿Hay alguna solución elegante que me falta o la conclusión es realmente "¿Requiere JavaScript o enviar todo"?
Respuestas:
Implementaría esto exactamente como lo describió: envíe todo al servidor y haga un simple if / else para verificar en qué botón se hizo clic.
Y luego implementaría una llamada de Javascript vinculada al evento de envío del formulario que verificaría antes de enviar el formulario, y solo enviaría los datos relevantes al servidor (posiblemente a través de un segundo formulario en la página con la ID necesaria para procesar la cosa como una entrada oculta, o actualice la ubicación de la página con los datos que necesita pasar como una solicitud GET, o haga una publicación de Ajax en el servidor, o ...).
De esta manera, las personas que no tienen Javascript pueden usar el formulario sin problemas, pero la carga del servidor se compensa porque las personas que tienen Javascript solo envían los datos necesarios. Centrarse en solo admitir uno u otro realmente limita sus opciones innecesariamente.
Alternativamente, si está trabajando detrás de un firewall corporativo o algo y todo el mundo tiene Javascript deshabilitado, es posible que desee hacer dos formularios y hacer algo de magia CSS para que parezca que el botón Eliminar es parte del primer formulario.
fuente
Sé que esta es una pregunta antigua, pero HTML5 ofrece un par de opciones nuevas.
El primero es separar el formulario de la barra de herramientas en el marcado, agregar otro formulario para la acción de eliminar y asociar los botones en la barra de herramientas con sus respectivos formularios utilizando el
form
atributo.Esta opción es bastante flexible, pero la publicación original también mencionó que puede ser necesario realizar diferentes acciones con un solo formulario. HTML5 viene al rescate, de nuevo. Puede usar el
formaction
atributo en los botones de envío, por lo que diferentes botones en el mismo formulario pueden enviar a diferentes URL. Este ejemplo solo agrega un método de clonación a la barra de herramientas fuera del formulario, pero funcionaría igual anidado en el formulario.http://www.whatwg.org/specs/web-apps/current-work/#attributes-for-form-submission
La ventaja de estas nuevas características es que hacen todo esto de manera declarativa sin JavaScript. La desventaja es que no son compatibles con navegadores más antiguos, por lo que tendría que realizar algunos rellenos polifónicos para navegadores más antiguos.
fuente
form=
- CanIUse realmente no dice. caniuse.com/#feat=forms<input>
para declarar botones. El<button>
elemento se introdujo hace 15 años para este propósito. Realmente personas.<input>
o<button>
es irrelevante, aunque los botones suelen ser más apropiados para las barras de herramientas, como usted dice. Por cierto, los elementos de los botones no han sido compatibles con todos los navegadores durante 15 años.¿Puede tener los formularios uno al lado del otro en la página, pero no anidados? luego usa CSS para hacer que todos los botones estén alineados
fuente
HTML5 tiene una idea de "propietario del formulario": el atributo "formulario" para los elementos de entrada. Permite emular formas anidadas y resolverá el problema.
fuente
Tipo de tema antiguo, pero este podría ser útil para alguien:
Como alguien mencionó anteriormente, puede usar la forma ficticia. Tuve que superar este problema hace algún tiempo. Al principio, me olvidé por completo de esta restricción de HTML y acabo de agregar los formularios anidados. El resultado fue interesante: perdí mi primera forma de la anidada. Luego resultó ser una especie de "truco" simplemente agregar un formulario ficticio (que se eliminará del navegador) antes de los formularios anidados reales.
En mi caso se ve así:
Funciona bien con Chrome, Firefox y Safari. IE hasta 9 (no estoy seguro acerca de 10) y Opera no detecta parámetros en la forma principal. $ _REQUEST global está vacío, independientemente de las entradas. Las formas internas parecen funcionar bien en todas partes.
No he probado otra sugerencia descrita aquí: conjunto de campos alrededor de formularios anidados.
EDITAR : Frameset no funcionó! Simplemente agregué el formulario Principal después de los otros (no más formularios anidados) y usé el "clon" de jQuery para duplicar las entradas en el formulario al hacer clic en el botón. Se agregó .hide () a cada una de las entradas clonadas para mantener el diseño sin cambios y ahora funciona de maravilla.
fuente
Creo que Jason tiene razón. Si su acción "Eliminar" es mínima, haga que esté en un formulario por sí mismo y alinéelo con los otros botones para que la interfaz se vea como un formulario unificado, incluso si no lo es.
O, por supuesto, rediseñe su interfaz y permita que las personas eliminen por completo cualquier otro lugar que no requiera que vean la enorme forma.
fuente
Una forma de hacerlo sin javascript sería agregar un conjunto de botones de radio que definan la acción a tomar:
Luego, el script de acción tomaría diferentes acciones dependiendo del valor del conjunto de botones de opción.
Otra forma sería poner dos formularios en la página como sugirió, simplemente no anidados. Sin embargo, el diseño puede ser difícil de controlar:
Usar el campo "tarea" oculto en el script de manejo para bifurcarse adecuadamente.
fuente
Esta discusión sigue siendo de mi interés. Detrás de la publicación original hay "requisitos" que el OP parece compartir, es decir, un formulario con compatibilidad con versiones anteriores. Como alguien cuyo trabajo al momento de escribir a veces debe ser compatible con IE6 (y en los años venideros), lo entiendo.
Sin impulsar el marco (todas las organizaciones van a querer tranquilizarse sobre la compatibilidad / robustez, y no estoy usando esta discusión como justificación para el marco), las soluciones de Drupal para este tema son interesantes. Drupal también es directamente relevante porque el marco ha tenido una política a largo plazo de "debería funcionar sin Javascript (solo si lo desea)", es decir, el problema del OP.
Drupal usa sus funciones form.inc bastante extensas para encontrar el triggering_element (sí, ese es el nombre en el código). Consulte la parte inferior del código que figura en la página API para form_builder (si desea profundizar en los detalles, se recomienda la fuente: drupal-x.xx / includes / form.inc ). El constructor utiliza la generación automática de atributos HTML y, a través de eso, puede detectar qué botón se presionó y actuar en consecuencia (estos pueden configurarse para ejecutar procesos separados también).
Más allá del generador de formularios, Drupal divide las acciones de 'eliminación' de datos en urls / formularios separados, probablemente por las razones mencionadas en la publicación original. Esto necesita algún tipo de paso de búsqueda / listado (¡ gruñe otra forma !, pero es fácil de usar) como preliminar. Pero esto tiene la ventaja de eliminar el problema de "enviar todo". La gran forma con los datos se usa para el propósito previsto, la creación / actualización de datos (o incluso una acción de 'fusión').
En otras palabras, una forma de solucionar el problema es delegar el formulario en dos, luego el problema desaparece (y los métodos HTML también pueden corregirse a través de un POST).
fuente
Use un
iframe
para la forma anidada. Si necesitan compartir campos, entonces ... no está realmente anidado.fuente
Mi solución es hacer que los botones llamen a funciones JS que escriben y luego envían formularios fuera del formulario principal
fuente
Si realmente no desea utilizar varios formularios (como sugiere Jason), utilice botones y controladores onclick.
Y luego en javascript (uso jQuery aquí para facilitarlo) (aunque es demasiado exagerado para agregar algunos controladores onclick)
También lo sé, esto hará que la mitad de la página no funcione sin JavaScript.
fuente
En respuesta a una pregunta publicada por Yar en un comentario a su propia respuesta, presento algunos JavaScript que redimensionarán un iframe. Para el caso de un botón de formulario, es seguro asumir que el iframe estará en el mismo dominio. Este es el código que uso. Tendrá que alterar las matemáticas / constantes para su propio sitio:
Entonces llámalo así:
fuente
Se me ocurrió una buena manera de hacerlo con jquery.
fuente
Bueno, si envía un formulario, el navegador también envía un nombre y un valor de envío de entrada. Entonces, lo que puedes hacer es
entonces, en el lado del servidor, solo busca el parámetro que comienza con la cadena de ancho "acción:" y el resto le dice qué acción tomar
así que cuando haces clic en el botón Guardar, el navegador te envía algo como foo = asd & action: save = Save
fuente
Abordé el problema al incluir una casilla de verificación dependiendo de la forma que la persona quería hacer. Luego usé 1 botón para enviar el formulario completo.
fuente
Alternativamente, podría asignar el formulario actiob sobre la marcha ... podría no ser la mejor solución, pero seguro alivia la lógica del lado del servidor ...
fuente