Botón del modal se queda seleccionado: cómo solucionarlo con una sola ventana para varios productos

La forma adecuada de abrir una sola ventana modal desde varios botones consiste en utilizar un atributo personalizado, como data-info, para guardar el producto seleccionado, y después copiar ese valor dentro del contenido de la modal cuando el usuario haga clic. De esta manera, todos los botones reutilizan la misma modal y cada uno muestra el producto correspondiente.

El problema aparece cuando se crea una modal diferente para cada producto o cuando se intenta utilizar un único id para identificar simultáneamente varios botones. Un id debe ser único dentro del documento, por lo que no es la opción adecuada para relacionar muchos botones con una sola ventana modal.

Una sola modal para varios botones

Esto nos sirve para manejar datos dinámicamente y solo tener una ventana modal, en vez de tener múltiples y hacer más pesada la página. Cabe aclarar que esto es dependiendo de las necesidades de cada quien.

El valor que vamos a enviar será el que está en el atributo “data-info” tú puedes pasar un array, un número o el valor que necesites.

Botones de los productos

Vamos a agregar 3 botones para abrir la misma ventana modal, en esta ocasión usaré Bootstrap para facilitar el CSS de la creación del modal.

El atributo data-info contiene el nombre que debe aparecer en la modal. Cada botón puede tener un valor diferente, aunque todos compartan la misma clase y la misma ventana modal.

Estructura de la ventana modal

En la etiqueta div con la clase modal-body pondremos la información que mandaremos.

El campo visible muestra el producto elegido y el campo oculto permite enviar ese mismo valor al archivo que procesa el formulario.

Obtener los datos con jQuery

Creamos la función click() para enviar los datos, en este ejemplo solo estamos enviando la información que se encuentra en el atributo data-info.

Cada vez que se da click en un botón se envía la respectiva info.

$(document).ready(function () { $(".btn-primary").click(function () { let info = $(this).data('info'); $('.producto-seleccionado').html(info); $('.producto-input').val(info); $('#ventana').modal('show'); console.log(info); });});

La expresión $(this) representa el botón que recibió el clic. Por eso, al consultar data('info'), se obtiene el producto específico asociado con ese botón.

El método html(info) coloca el nombre del producto dentro de la modal, mientras que val(info) asigna el mismo dato al campo oculto del formulario.

El resultado es que todos los botones abren la misma ventana modal y la información se actualiza antes de mostrarla.

modal Bootstrap con botones de productos

Activar la modal desde Bootstrap

También puedes indicar directamente en los botones que deben abrir la ventana modal utilizando los atributos de Bootstrap.

En este caso, data-target="#ventana" indica que todos los botones deben abrir la misma modal, cuyo identificador es ventana.

Cuando Bootstrap se encarga de abrir la ventana, el código solo necesita actualizar la información del producto seleccionado.

$(document).ready(function () { $(".btn-primary").click(function () { let info = $(this).data('info'); $('.producto-seleccionado').html(info); $('.producto-input').val(info); });});

Usar una clase en lugar de un id para los botones

Para seleccionar varios botones no debes repetir el mismo id. En su lugar, utiliza una clase común, por ejemplo btn-cotizar.

Después, el selector de jQuery debe utilizar esa clase.

$(document).ready(function () { $(".btn-cotizar").click(function () { let info = $(this).data('info'); $('.producto-seleccionado').text(info); $('.producto-input').val(info); });});

La clase puede repetirse en todos los botones, mientras que el id de la modal debe permanecer único.

Enviar el producto elegido al archivo PHP

Si el formulario utiliza method="POST", el nombre del producto puede enviarse mediante un campo oculto.

<input type="hidden" name="producto" class="producto-input">

Cuando el usuario pulsa el botón de cotización, el valor se coloca en ese campo.

$('.producto-input').val(info);

Después, el botón de envío transmite el formulario a procesar.php.

<button type="submit" class="btn btn-primary">Procesar</button>

El archivo PHP recibirá el valor enviado mediante el campo cuyo nombre es producto.

$producto = $_POST['producto'];

El formulario del ejemplo utiliza la siguiente estructura.

<form name="codigo_nuevo" action="procesar.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="producto" class="producto-input"> <button type="submit" class="btn btn-primary"> Procesar </button></form>

Diferencia entre type="button" y type="submit"

Eso quiere decir que es solo un Boton, al presionarlo no pasara nada aun que este dentro del Form por que es Tipo Boton.

Si cambiaras el type button por: type="submit" si funciona, Envía el Formulario ya que es de tipo Submit/Envio.

Un botón con type="button" no envía el formulario automáticamente. Ese tipo se utiliza para ejecutar una acción mediante JavaScript o para realizar una acción que no debe enviar los datos.

Un botón con type="submit" envía el formulario hacia la dirección indicada en el atributo action, utilizando el método definido en method.

Tipo de botónComportamiento
type="button"No envía el formulario automáticamente.
type="submit"Envía el formulario al archivo indicado en action.

Pero Claro a los Tipo botones también puedes hacer que se envíen los Formularios mediante JS o Jquery ;)

Botón de procesamiento dentro del pie de la modal

Si quieres que el botón de procesamiento esté en el pie de la ventana, puede permanecer dentro del formulario siempre que tenga el tipo adecuado.

En este caso, Procesar 2 enviará el formulario porque utiliza type="submit". El botón Cerrar utiliza type="button" junto con data-dismiss="modal" porque su función es cerrar la ventana y no enviar los datos.

Alternativa mediante una función obtenerInfo()

La opción 2 utiliza el evento onclick que está en cada botón, de esta manera estamos ejecutando la función obtenerInfo(datos, objetivo).

La función obtenerInfo() recibe 2 parámetros:

  • Datos: La información que se envía al modal.
  • Objetivo: Donde se mostrará la información del primer parámetro.

La estructura se ve muy parecida a la opción 1.

function obtenerInfo(datos, objetivo) { $(`.${objetivo}`).html(datos);}

Para enviar también el producto al formulario, la función puede actualizar el campo oculto.

function obtenerInfo(datos, objetivo) { $(`.${objetivo}`).html(datos); $('.producto-input').val(datos);}

Esta alternativa funciona, aunque el uso de un atributo como data-info permite mantener separados el contenido HTML y el comportamiento JavaScript.

Evitar que quede seleccionado el producto anterior

El dato anterior puede permanecer visible si la modal no actualiza todos sus elementos al abrirse. Para evitarlo, asigna el nuevo producto tanto al texto mostrado como al campo oculto cada vez que se pulsa un botón.

$(".btn-cotizar").on("click", function () { const producto = $(this).attr("data-info"); $(".producto-seleccionado").text(producto); $(".producto-input").val(producto);});

Antes de mostrar la modal, el valor anterior se reemplaza por el valor del botón seleccionado.

Si la modal se cierra y vuelve a abrirse, el mismo procedimiento se ejecuta nuevamente con el nuevo botón.

Ejemplo completo

El siguiente ejemplo reúne los botones, la modal, el producto visible, el campo oculto y el botón que envía el formulario.

<button type="button" class="btn-cotizar" data-toggle="modal" data-target="#ventana" data-info="Producto X"> Cotizar producto X</button><button type="button" class="btn-cotizar" data-toggle="modal" data-target="#ventana" data-info="Producto Y"> Cotizar producto Y</button><div class="modal fade" id="ventana" data-backdrop="static"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">Cotizar producto</h4> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> &times; </button> </div> <div class="modal-body"> <p> Usted eligió cotizar el producto: <strong class="producto-seleccionado"></strong> </p> <form action="procesar.php" method="POST"> <input type="hidden" name="producto" class="producto-input"> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> Cerrar </button> <button type="submit" class="btn btn-primary"> Procesar </button> </div> </form> </div> </div> </div></div>
$(document).ready(function () { $(".btn-cotizar").click(function () { let producto = $(this).data("info"); $(".producto-seleccionado").text(producto); $(".producto-input").val(producto); });});

Con esta estructura, el botón del producto X abre la modal con el producto X, el botón del producto Y abre la misma modal con el producto Y y el formulario recibe el valor correspondiente.

Formulario Bootstrap SpringBoot Usuario Parte04 CRUD Validacion Modal

tags: #boton #modal #se #queda #seleccionado