Tengo un formulario donde se pueden agregar filas al hacer clic en un botón. También se pueden eliminar con un clic.
Mi html en la carga de la página se ve así:
<div class="invoicerow"> <div class="row"> <div class="col-12 col-md-2"> <label for="">Aantal</label> <div class="inputstyle mb-10"> <input type="text" name="invoice_row[][invoice_quantity]"> </div> </div> <div class="col-12 col-md-5"> <label for="">Titel</label> <div class="inputstyle mb-10"> <input type="text" name="invoice_row[][invoice_title]"> </div> </div> <div class="col-12 col-md-2"> <label for="">Prijs</label> <div class="inputstyle mb-10"> <input type="text" name="invoice_row[][invoice_price]"> </div> </div> <div class="col-12 col-md-2"> <label for="">Totaal</label> <div>€99,05</div> </div> <div class="col-12 col-md-1 d-flex align-center"> <i class="fas fa-trash-alt delete_invoice_row"></i> </div> <div class="col-12"> <label for="">Beschrijving</label> <div class="inputstyle mb-10"> <textarea type="text" name="invoice_row[][invoice_desc]"></textarea> </div> </div> </div> </div> Quiero agrupar todos los resultados cuando hay varios elementos de invoicerow de facturas presentes.
Ahora, cuando publico, la matriz publicada se ve así:
Array ( [other_info] => [invoice_row] => Array ( [0] => Array ( [invoice_quantity] => ) [1] => Array ( [invoice_title] => ) [2] => Array ( [invoice_price] => ) [3] => Array ( [invoice_desc] => ) [4] => Array ( [invoice_quantity] => ) [5] => Array ( [invoice_title] => ) [6] => Array ( [invoice_price] => ) [7] => Array ( [invoice_desc] => ) ) )Si bien esto es lo que estoy buscando:
Array ( [other_info] => [invoice_row] => Array ( [0] => Array ( [invoice_quantity] => [invoice_title] => [invoice_price] => [invoice_desc] => ) [1] => Array ( [invoice_quantity] => [invoice_title] => [invoice_price] => [invoice_desc] => ) ) ) Sé que puedo cambiar esta invoice_row[][invoice_price] a invoice_row[0][invoice_price] por ejemplo para agruparlos, pero esto no funcionará ya que mis campos de entrada se pueden agregar y eliminar dinámicamente.
¿Cuál es la mejor solución para esto?
Este es mi código que agrega y elimina los campos de entrada:
$(".add_invoice_row").click(function () { var invoicehtml = '' + '<div class="invoicerow">' + ' <div class="row">' + ' <div class="col-12 col-md-2">' + ' <label for="">Aantal</label>' + ' <div class="inputstyle mb-10">' + ' <input type="text" name="invoice_row[][invoice_quantity]">' + ' </div>' + ' </div>' + ' <div class="col-12 col-md-5">' + ' <label for="">Titel</label>' + ' <div class="inputstyle mb-10">' + ' <input type="text" name="invoice_row[][invoice_title]">' + ' </div>' + ' </div>' + ' <div class="col-12 col-md-2">' + ' <label for="">Prijs</label>' + ' <div class="inputstyle mb-10">' + ' <input type="text" name="invoice_row[][invoice_price]">' + ' </div>' + ' </div>' + ' <div class="col-12 col-md-2">' + ' <label for="">Totaal</label>' + ' <div>€99,05</div>' + ' </div>' + ' <div class="col-12 col-md-1 d-flex align-center">' + ' <i class="fas fa-trash-alt delete_invoice_row"></i>' + ' </div>' + ' <div class="col-12">' + ' <label for="">Beschrijving</label>' + ' <div class="inputstyle mb-10">' + ' <textarea type="text" name="invoice_row[][invoice_desc]"></textarea>' + ' </div>' + ' </div>' + ' </div>' + '</div>' + ''; $('.new_invoice_row').append(invoicehtml); create_invoice_form = $(".create_invoice_form").serialize(); $.ajax({ type:'post', url:"invoice_custom.php", data:({ create_invoice_form: create_invoice_form }), success:function(data){ console.log(data); } }); }); $(document).on('click', '.delete_invoice_row', function () { $(this).closest('.invoicerow').remove(); });Ejemplo jsFiddle: https://jsfiddle.net/xbLyp9f2/1/
En mi humilde opinión: no incruste HTML literal en su código JS a menos que sea realmente necesario. Oculte la plantilla HTML en una etiqueta de secuencia de comandos que contenga marcadores de texto de reemplazo (por ejemplo, para el índice).
Luego puede insertar un valor de índice real para cada fila agregada (generalmente agrego 1 al valor de fila más alto existente presente):
<script id="rowtemplate"> <div class="invoicerow"> <div class="row"> <div class="col-12 col-md-2"> <label for="">Aantal</label> <div class="inputstyle mb-10"> <input type="text" name="invoice_row[{row}][invoice_quantity]"> </div> </div> <div class="col-12 col-md-5"> <label for="">Titel</label> <div class="inputstyle mb-10"> <input type="text" name="invoice_row[{row}][invoice_title]"> </div> </div> <div class="col-12 col-md-2"> <label for="">Prijs</label> <div class="inputstyle mb-10"> <input type="text" name="invoice_row[{row}][invoice_price]"> </div> </div> <div class="col-12 col-md-2"> <label for="">Totaal</label> <div>{total}</div> </div> <div class="col-12 col-md-1 d-flex align-center"> <i class="fas fa-trash-alt delete_invoice_row"></i> </div> <div class="col-12"> <label for="">Beschrijving</label> <div class="inputstyle mb-10"> <textarea type="text" name="invoice_row[{row}][invoice_desc]"></textarea> </div> </div> </div> </div> </script> $('#rowtemplate').html() le dará la plantilla como una cadena.
https://jsfiddle.net/TrueBlueAussie/j41fzubp/2/
Dejé un comentario en el JSFiddle donde irían los reemplazos de cadenas, pero como ya ha aceptado otra respuesta, dejo que lo complete.
Para que la solución dinámica (agregar los índices a los nombres de los formularios explícitamente) funcione de manera confiable, todo lo que necesita hacer es manejar la reindexación cuando elimina un elemento:
$(document).on('click', '.delete_invoice_row', function () { $(this).closest('.invoicerow').remove(); $('.invoicerow').each(function(idx, el) { $(el).find('[name^="invoice_row"]').each(function(iidx, iel) { $(iel).attr("name", iel.name.replace(/invoice_row\[\d+\]/, "invoice_row[" + idx + "]")); }); }); });Violín: https://jsfiddle.net/fg8rwexp/2/