Clone a table and clone text fields within it

1

I have a problem when cloning a complete table in JavaScript: pressing the button that allows me to clone the table deactivates me the buttons that allow me to clone text fields inside it; and vice versa: if I press the buttons inside the table that clone me the text fields, I disable the buttons that allow me to clone the table.

The following image shows how the tables I want to implement are:

And this is the code I use:

$(document).ready(function() {
  tabla = $('#tabla');

  $('#agregartabla').live('click', function() {
    $(this).parents(".cl1").clone().appendTo("div#cl0").find(':text').val('');
  });

  $(".eliminartabla").live('click', function() {
    $(this).closest(".cl1").remove();
  });

  $('#btnAdd').click(function() {
    var num = $('.clonedInput').length;
    var newNum = new Number(num + 1);
    var newElem = $('#input' + num).clone().attr('id', 'input' + newNum);

    newElem.children(':first').attr('id', 'name' + newNum)
      .attr('name', 'name' + newNum).find(':text').val('');

    $('#input' + num).after(newElem);
    $('#btnDel').attr('enabled', '');
    if (newNum == 10)
      $('#btnAdd').attr('disabled', 'disabled');
  });

  $('#btnDel').click(function() {
    var num = $('.clonedInput').length;
    
    $('#input' + num).remove();
    $('#btnAdd').attr('enabled', '');
    if (num - 1 == 0)
      $('#btnDel').attr('disabled', 'disabled');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>

<div id="cl0">
  <div id="cl1" class="cl1">
    <input type="button" value="Agregar" id="agregartabla">
    <input type="button" value="Eliminar" class="eliminartabla">
    <table width="70%" border="2" id="tabla">
      <tr>
        <td>
          <ol>
            <li>ARTICULO<input type="text" name="name2" id="name2" /></li>
          </ol>
        </td>
        <td>
          <ol>
            <div id="input1" class="clonedInput">
              <li>MARCA<input type="text" name="name3" id="name3" /></li>
            </div>
          </ol>
          <input type="button" id="btnAdd" value="AGREGAR MARCA" />
          <input type="button" id="btnDel" value="BORRAR MARCA" />
        </td>
      </tr><br>
    </table><br>
  </div>
</div>
    
asked by josearegu 03.07.2017 в 19:23
source

3 answers

1

An alternative that I have is the following, but it has a small problem of duplication of the internal nested table row, that when cloning this internal row is cloned equally in all the external tables added.

$(function(){
                $(document).on('click',"#agregartablauno" , function(){                
                $("#tablauno tbody tr:eq()").clone()
                    .append('<td class="eliminartablauno"><input type="button" value="ELIMINAR"/></td>')
                    .appendTo("#tablauno");         
                });
                
                $(document).on("click",".eliminartablauno",function(){
                var parent = $(this).parent();
                $(parent).remove();
                });
           
                $(this).on('click', ".agregartablados" , function(){                
                $(".tablados tbody tr:eq()").clone()
                    .append('<td class="eliminartablados"><input type="button" value="-"/></td>')
                    .appendTo(".tablados");         
                });

                $(document).on("click",".eliminartablados",function(){
                var parent = $(this).parent();
                $(parent).remove();
                });
            });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
    <html>
    <head><title>I</title>

    <script>
    </script>
    </head>
    <body><center>
       <table id="tablauno" align="center" >
         <tr>
           <td>
             ARTICULO <input type="text" name="txtarticulo" size=32 />
           </td>                                         
           <td>
            <table class="tablados">
                <thead>
                  <tr>
                     <td>MARCA</td>                                
                  </tr>
                 </thead>
                 <tbody>
                   <tr id="fila-base">
                      <td><input id="txtmarca" name="txtmarca" type="text" /></td>                                
                   </tr>
                  </tbody>
            </table> 
            <input class="agregartablados" type="button" value="+" /> 
          </td>            
        </tr>
       </table>
       <input id="agregartablauno" type="button" value="AGREGAR"> <br><br>
    </center></body>
    </html>
    
answered by 18.07.2017 в 03:00
0

I can reproduce the first problem: if the table is cloned, the buttons inside the table are "deactivated", but not vice versa as you say in the question. I'm going to focus on that failure.

The error occurs due to a series of problems:

  • When you add / delete fields from the table, you count the number of cloned fields and then try to add the field with ID "#input" + número de campos clonados after or delete the field with ID "#input" + número de campos clonados respectively. That is why it works when there is only one table: the number of cloned fields matches the number of available fields and then the IDs to be added / deleted coincide without problems. But when there is more than one table, you count the number of cloned fields that is greater than the IDs of the fields in the tables (see problem on duplicate IDs below). The solution would be not to count the total number of cloned fields, but the number of fields cloned within that particular table . And then add and delete but only within that particular table.
  • You have repeated IDs. You do not have them at the beginning, but once you clone the tables, clone the fields with their respective IDs and the problem of the repeated IDs appears. Initially I thought the problem was this and, although it really is not, the problem partly stems from this.
  • You are using a version of jQuery (1.7) that is outdated and that includes methods (that you use) that are considered obsolete and that have been removed from more modern versions (eg live ). You should switch to a more modern version of jQuery, update your code and use more appropriate functions like on . This really is not the cause of the problem, but it is highly recommended, even if you keep the jQuery version you could use on .
  • Event handlers are not being associated correctly for the "Add Mark" and "Clear Mark" buttons. This happens because they are associating before they are cloned and then the clones do not have those associated drivers. This could be solved using live instead of click (although I do not recommend it for the previous point, it would be better to delegate events with on ); another option would be passing the parameter true to clone (so that the events associated with the cloned event will be maintained)

I have changed your code a little to adapt it to what I say above:

  • Removing the IDs that will be duplicated and replacing them with classes.
  • Changing live to on .
  • Using delegated events.
  • Limiting the scope of the accounts to the table on which you are operating instead of the entire document.

With those changes, the code would look like this and it works:

$(document).ready(function() {

  $("body").on('click', '.agregartabla', function() {
    $(this).parents(".cl1").clone().appendTo("div#cl0").find(':text').val('');
  });

  $("body").on('click', ".eliminartabla", function() {
    $(this).closest(".cl1").remove();
  });

  $("body").on("click", '.btnAdd', function() {
    var tabla = $(this).closest(".tabla");
    var num = tabla.find('.clonedInput').length;
    var newNum = new Number(num + 1);
    var newElem = tabla.find('.input' + num).clone().attr('class', 'input' + newNum + ' clonedInput');

    newElem.children(':first').attr('class', 'name' + newNum)
      .attr('name', 'name' + newNum).find(':text').val('');

    tabla.find('.input' + num).after(newElem);
    tabla.find('.btnDel').attr('enabled', '');
    if (newNum == 10)
      tabla.find('.btnAdd').attr('disabled', 'disabled');
  });

  $("body").on("click", '.btnDel', function() {
    var tabla = $(this).closest(".tabla");
    var num = tabla.find('.clonedInput').length;
    
    tabla.find('.input' + num).remove();
    tabla.find('.btnAdd').attr('enabled', '');
    if (num - 1 == 0)
      tabla.find('.btnDel').attr('disabled', 'disabled');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>

<div id="cl0">
  <div id="cl1" class="cl1">
    <input type="button" value="Agregar" class="agregartabla">
    <input type="button" value="Eliminar" class="eliminartabla">
    <table width="70%" border="2" class="tabla">
      <tr>
        <td>
          <ol>
            <li>ARTICULO<input type="text" name="name2" class="name2" /></li>
          </ol>
        </td>
        <td>
          <ol>
            <div class="input1 clonedInput">
              <li>MARCA<input type="text" name="name3" class="name3" /></li>
            </div>
          </ol>
          <input type="button" class="btnAdd" value="AGREGAR MARCA" />
          <input type="button" class="btnDel" value="BORRAR MARCA" />
        </td>
      </tr><br>
    </table><br>
  </div>
</div>
answered by 06.07.2017 в 15:38
0

To clone an HTML Element, Vanilla JavaScript provides the method Node.cloneNode (deep) .

const table = document.querySelector('table');
const clonedTable = table.cloneNode(true);

To add an HTML Element after an HTML Element, Vanilla JavaScript provides the Element method .insertAdjacentElement (pos, text) .

const el = document.querySelector('#container');
el.insertAdjacentElement('afterend', clonedTable);
    
answered by 06.01.2018 в 11:42