Dynamically adding element with jQuery

Asked

Viewed 9,742 times

12

I have assembled the following structure in HTML:

<form name="criaModelo" method='post' action=''>
  <label for="name">
    <strong>Nome:</strong>
    <input name="nomeModelo" type="text">
  </label>

  <h2>Associando Instruções</h2>

  <img src="images/4.png" class="btnNewInst btnHover" title="Inserir nova instrução" />

  <label for="criaAssoc" class="instAssoc">
    <strong>ID:</strong>
    <input type="text">
    <strong>Ordem:</strong>
    <input type="text">

    <span>
      <strong class="instTxt">Instrução:</strong>
      <textarea disabled="disabled"></textarea>
    </span>
  </label>

  <h2>Associando Tempo</h2>

  <img src="images/4.png" class="btnNewTime btnHover" title="Inserir nova instrução" />

  <label class="time">
    <strong>ID:</strong>
    <input type="text" style="width:25px;">
    <div>
      <strong>Total:</strong>
      <span>12:12:12</span>
      <strong class="margem">Tipo:</strong>
      <span>visível</span>
      <strong class="margem">Momento:</strong>
      <span>12:12:12</span>
      <strong class="margem">Ordem:</strong>
      <span>Crescente</span>
    </div>
  </label>

  <input type="submit" name="btnCriaModelo" class="newbtn" value="Criar"> 
</form>

Which has the following result: Captura de Tela

I wanted to click on this button to add to the form after the last current element of this HTML to create a new label as above.

<label for="criaAssoc" class="instAssoc">
  <strong>ID:</strong>
  <input type="text">
  <strong>Ordem:</strong>
  <input type="text">

  <span>
    <strong class="instTxt">Instrução:</strong>
    <textarea disabled="disabled"></textarea>
  </span>
</label>

2 answers

11


I suggest you keep this label as a template (i.e. leave it in its initial, empty, and invisible state), and clone others from him:

<label id="meuTemplate" for="criaAssoc" class="instAssoc" style="display:none">
    ...
</label>
var clone = $("#meuTemplate").clone();
clone.prop("id", novoId); // É necessário mudar o id depois que se clona

So you can select the last label and insert after it:

$(".instAssoc:last").after(clone);
clone.show();

Example in jsFiddle.

Updating: to access a particular item within of this item you just created, see the function .find (it searches for all descendants). And if you want an element to exclude itself, use the function .remove (or .detach, if you intend to reinsert this element into the DOM later; e.g.: drag-and-drop / drag-and-drop). Example:

clone.find(".botaoExcluir").click(function() {
    clone.remove();
});

Updated example.

  • What if I had a button inside each label to delete it?

  • @Luitame The simplest solution is to add the Handler to deal with the click the same time you clone. I updated the answer with an example.

5

Come on, I know the question is what it would be like to use jQuery, but I prefer to answer how it should be done in the best way, since what you want to do will be replicated several times in your project (other screens with similar or even more complex behaviors) and a MVVM library falls like a glove. As an example, I quote my favorite knockoutjs.

Libraries of MVVM abstract task of the programmer in having to synchronize the user interface with the data and knockoutjs does it in a very semantic way, basically it is possible to create extremely complex behaviors without there being any coupling between the data that you want to work the view.

As an example, I did this little Plunk. Click on the "Code" tab and then on script.js and then on index.html and see how simple it is to work with it.

-----update

As suggested, below is all the code used in the solution, which, as you can see, is very simple and easy to understand.

Javascript

var 
    minhaView = {

        //lista de registros
        registros: ko.observableArray([]),
        id: ko.observable(""),
        ordem: ko.observable(""),

        incluirNovo: function(el) {

          //incluo na lista
          this.registros.push({id: this.id(),ordem: this.ordem()});

          //limpo textboxes
          this.id(""), this.ordem("");
        }
      }

ko.applyBindings(minhaView);

HTML

<label for="txtId">ID</label>
<input type="text" id="txtId" data-bind="value: id" />
<label for="txtOrdem">Ordem:</label>
<input type="text" id="txtOrdem" data-bind="value: ordem"/>
<button data-bind="click: incluirNovo">+</button>
<h2>Relação de itens</h2>
<ul data-bind="foreach: registros(), visible: registros().length > 0">
    <li>ID: <span data-bind="text: id"></span> - Ordem:<span data-bind="text: ordem"></span>
    </li>
</ul>
<span data-bind="visible: registros().length===0">Ainda não existem itens registrados.</span>
  • 1

    I also use knockout.js, I even thought about it when I saw the question, but preferred to answer using the requested technology. However, your suggestion is very useful, I just suggest that you include an example code (you don’t need to copy the whole Plunk, only the relevant section), because the way it is now the usefulness of the answer is linked to the link.

  • @mgibsonbr, although I don’t think it’s necessary, I will update as proposed.

Browser other questions tagged

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