Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

475
Visualizações
How to group values posted from HTML form by key if input fields can be dynamically added or deleted

I have a form where rows can be added on click of a button. They can also be removed on click.

My html on page load looks like this:

<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>

I want to group all results together when there are multiple invoicerow elements present.

Now when I post the posted array looks like this:

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] => 
                )

        )

)

While this is what I am looking for:

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] => 
                )

        )

)

I know I can change this invoice_row[][invoice_price] to invoice_row[0][invoice_price] for example to group them but this won't work since my input fields can be dynamically added and removed.

What is the best solution for this?

This is my code that adds and removes the input fields:

$(".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();
});

jsFiddle example: https://jsfiddle.net/xbLyp9f2/1/

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

You can use jquery.serializeJSON, a small jquery plugin, to get output in nice JSON format. The JSON can be easily parsed at server side.

$(".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);
  }
});
*/
function onSubmit(form) {
  var data = $(form).serializeJSON();

  console.log(data);
  console.log(JSON.stringify(data, undefined, 3));
  return false;
}

$(document).on('click', '.delete_invoice_row', function() {
  $(this).closest('.invoicerow').remove();
});
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.serializeJSON/3.2.1/jquery.serializejson.min.js"></script>
<div class="col-12">
  <p>See the console logs for output.</p>
  <form class="create_invoice_form" method="post" onsubmit='return onSubmit(this)'>
    <button type='submit'>Submit</button><br><hr>
    <div class="row">
      <div class="col-12 col-md-6">
        <label for="">Emailadres</label>
        <div class="inputstyle mb-10">
          <input type="text" name="invoice[mail]" value='abc@gmail.com'>
        </div>
      </div>
      <div class="col-12 col-md-6">
        <label for="">Datum</label>
        <div class="inputstyle mb-10">
          <input type="date" name="invoice[date]">
        </div>
      </div>
      <div class="col-12">
        <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]" value='10'>
              </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]" value='item 1'>
              </div>
            </div>
            <div class="col-12 col-md-2">
              <label for="">Prijs ex. BTW</label>
              <div class="inputstyle mb-10">
                <input type="text" name="invoice[row][][invoice_price]" value='btw'>
              </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]">description</textarea>
              </div>
            </div>
          </div>
        </div>
        <div class="new_invoice_row">

        </div>
      </div>
    </div>
  </form>
</div>
<div class="col-12">
  <i class="fas fa-plus-square add_invoice_row"></i>
</div>

Note how I named the inputs invoice[row][][invoice_quantity].

Output:

{
   "invoice": {
      "mail": "abc@gmail.com",
      "date": "",
      "row": [
         {
            "invoice_quantity": "10",
            "invoice_title": "item 1",
            "invoice_price": "btw",
            "invoice_desc": "description"
         },
         {
            "invoice_quantity": "a",
            "invoice_title": "t",
            "invoice_price": "g",
            "invoice_desc": "sd"
         },
         {
            "invoice_quantity": "3",
            "invoice_title": "3",
            "invoice_price": "3",
            "invoice_desc": "des3"
         }
      ]
   }
}

In php you can convert the request JSON string to object using $jObj = json_decode($jsonString);

over 4 years ago · Santiago Trujillo Relatório

0

For the dynamic solution (adding the indexes to the form names explicitly) to work reliably, all you need to do is handle the re-indexing when you remove an item:

$(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 + "]"));
    });
  });
});

Fiddle: https://jsfiddle.net/fg8rwexp/2/

over 4 years ago · Santiago Trujillo Relatório

0

IMHO: Don't embed HTML literal into your JS code unless really needed. Hide the HTML template in a script tag containing replacement text markers (e.g. for the index).

You can then have an actual index value inserted for each added row (I usually add 1 to the highest existing row value present):

<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() will give you the template as a string.

https://jsfiddle.net/TrueBlueAussie/j41fzubp/2/

I left a comment in the JSFiddle where the string replacements would go, but as you have already accepted another answer, I leave it up to you to complete.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda