How to make a dynamic form?

Asked

Viewed 11,484 times

11

I implemented a script that dynamically adds fields to a form, in this case a form to add products and their amount.

The code is here: http://jsfiddle.net/3Lzcn7dc/

I find this code very bureaucratic, because every time the "New product" button is triggered, it is necessary to do:

  1. Clone the div item
  2. Change the id of the div and the fields productId and Quant
  3. Use a counter to increment ids and Names to ensure they are not equal
  4. Use an Hidden attribute (itemCont) to pass to the server the amount of new products that have been created, to know how many times I will have to call $_POST["productoId__"], as there may be hundreds of products created.

I would like the opinion of colleagues to perfect this code, making it leaner. Below follows the code:

HTML:

<form action="cadastro.php" method="post" id="formulario">
    <input type="button" id="novoProd" value="Novo produto"/>
    <input type="submit" value="enviar"/>
    <div id="item" class="item">
        <label>Selecione o produto:</label>
            <select id="produtoId" name="produtoId">
                <option value="1">Produto 1</option>
                <option value="5">Produto 2</option>
                <option value="9">Produto 3</option>
            </select>
        <label>Quantidade: </label>
        <input type="number" id="quant" name="quant"/>
    </div>
    <input type="hidden" id="itemCont" value="1"/>
</form>

JAVASCRIPT:

$(document).ready(function(){
    var itemCont = 1;
    $("#novoProd").click(function(){
        var novoItem = $("#item").clone();

        // modifica o id do item recem criado
        $(novoItem).attr("id","item"+itemCont);
        var novoSelect = $(novoItem).children()[1];
        $(novoSelect).attr("id","produtoId"+itemCont);
        $(novoSelect).attr("name","produtoId"+itemCont);

        var novoSelect = $(novoItem).children()[3];
        $(novoSelect).attr("id","quant"+itemCont);
        $(novoSelect).attr("name","quant"+itemCont);

        $("#formulario").append(novoItem);
        itemCont++;
        $("#itemCont").val(itemCont);
    });
  });
  • I recently had the same need and arrived at the same solution: Using the clone. I don’t think the code is bureaucratic. Obs: The difference is that it used ASP.net MVC

2 answers

8


A suggestion would be to use the names of inputs as Array and treat in PHP, example:

$(document).ready(function() {
      $("#novoProd").click(function() {
      var novoItem = $("#item").clone().removeAttr('id'); // para não ter id duplicado
      novoItem.children('input').val(''); //limpa o campo quantidade
      $("#formulario").append(novoItem);
    });
  });
input[type="number"] {
  width: 50px;
}
label {
  font-weight: bold;
  margin-left: 10px;
}
div.item {
  border: 1px solid black;
  padding: 10px;
  margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form action="cadastro.php" method="post" id="formulario">
  <input type="button" id="novoProd" value="Novo produto" />
  <input type="submit" value="enviar" />
  <div id="item" class="item">
    <label>Selecione o produto:</label>
    <select name="produtoId[]">
      <option value="1">Produto 1</option>
      <option value="5">Produto 2</option>
      <option value="9">Produto 3</option>
    </select>
    <label>Quantidade:</label>
    <input type="number" name="quant[]" />
  </div>
</form>

PHP

In PHP you make a foreach in the POST[produtoId] to do the insert at the base

foreach ($_POST['produtoId'] as $key=> $value){
    echo $value; // Id do produto
    echo $_POST['quant'][$key]; // Quantidade
}

This would avoid the manipulations in id's of input's, reducing your jQuery code and in a way simplifying the insert with PHP.

  • 1

    in that case the itemCont field can also be deleted

  • 1

    @Borachio, correct I just edited

  • 1

    Yes, the solution is much cleaner.

  • @abfurlan in the example above, shows how to add more fields, and how would it be to remove the added fields? It just adds...

  • 1

    @Alexandrelopes would look something like this. https://jsfiddle.net/af2t19k7/1/, has a problem if you remove the first one, but you can think about how to treat it, I just showed you an example.

  • 1

    @Alexandrelopes another version treating the above error: https://jsfiddle.net/vx4j0myk/

  • 1

    Thank you very much! @abfurlan excellent, well complete!

  • 1

    @abfurlan tried to put the buttons just below the inputs, but it seems that are being added the divs after the buttons see: https://jsfiddle.net/8td61mk4/

  • 1

    @Alexandrelopes To solve this you can create another div and append it. https://jsfiddle.net/ms4kf93t/

  • 1

    @abfurlan I am using bootstrap, I had to make new Ivs to group each label/input, I made some adjustments and it worked cool. There is only one problem... He is not clearing the value of the new inputs, he takes the value he puts in the first and plays in the next. See: https://jsfiddle.net/tcofd0mj/1 - would it also be possible to limit by e.g. max. 10 clones? Should I create a new question?

  • 1

    @abfurlan I managed to correct, I just altered Children for find of novoItem.children('input'), for novoItem.find('input'). Result: https://jsfiddle.net/j54nsky8/ --- What it would be like to limit clones?

  • 1

    @Alexandrelopes to limit you can create a simple if, https://jsfiddle.net/a6g29nvj/

  • 1

    @abfurlan Excellent! I adapted to my code, it worked 100%.

Show 8 more comments

0

Boy, to make this more dynamic you would have to write more code. But the elements could be removed from your html. But when I’m going to do something like I need dynamic id. I do it like this:

$(document).ready(function(){
    $("#novoProd").click(function(){
        var novoItem = $("#item").clone();
        var novoId = Math.floor((Math.random() * 100) + 1);

        // modifica o id do item recem criado
        $(novoItem).attr("id","item"+ novoId);
        var novoSelect = $(novoItem).children()[1];
        $(novoSelect).attr("id","produtoId"+ novoId);
        $(novoSelect).attr("name","produtoId"+ novoId);

        var novoSelect = $(novoItem).children()[3];
        $(novoSelect).attr("id","quant"+ novoId);
        $(novoSelect).attr("name","quant"+ novoId);

        $("#formulario").append(novoItem);
    });
  });

Or instead of saving the counter to a hidden input element. You could create a date attribute. For example:

<form action="cadastro.php" method="post" id="formulario">
    <input type="button" id="novoProd" value="Novo produto" data-index="1"/>
    <input type="submit" value="enviar"/>
    <div id="item" class="item" >
        <label>Selecione o produto:</label>
            <select id="produtoId" name="produtoId">
                <option value="1">Produto 1</option>
                <option value="5">Produto 2</option>
                <option value="9">Produto 3</option>
            </select>
        <label>Quantidade: </label>
        <input type="number" id="quant" name="quant"/>
    </div>
    <input type="hidden" id="itemCont" value="1"/>
</form>

$(document).ready(function(){

    $("#novoProd").click(function(){
        var itemCont = $("#novoProd").attr("data-index");
        var novoItem = $("#item").clone();

        // modifica o id do item recem criado
        $(novoItem).attr("id","item"+itemCont);
        var novoSelect = $(novoItem).children()[1];
        $(novoSelect).attr("id","produtoId"+itemCont);
        $(novoSelect).attr("name","produtoId"+itemCont);

        var novoSelect = $(novoItem).children()[3];
        $(novoSelect).attr("id","quant"+itemCont);
        $(novoSelect).attr("name","quant"+itemCont);

        $("#formulario").append(novoItem);
        itemCont++;
        $("#novoProd").attr("data-index",itemCont);
    });
  });

Browser other questions tagged

You are not signed in. Login or sign up in order to post.