1

I'm trying to find out if it's possible to clone an HTML div with JS, edit it and append it again as a new element. So my source is, for example, this code here:

<div class="wrapper">
    <div class="element">
        <input id="test--1" value="ABC"/>
    </div>
</div>

After copying this element, I need to find a way to change the attribute id of the new cloned input, clear the input value and paste it again in the wrapper so that it looks like this at the end:

<div class="wrapper">
    <div class="element">
        <input id="test--1" value="ABC"/>
    </div>
    <div class="element">
        <input id="test--2" value=""/>
    </div>
</div>

Does that make sense to you? If yes, how can I get this done? Or is it better to assign the content to a variable to append it? I'm looking for the best way here and maybe my idea is a solution too.

AndrewL64
  • 15,794
  • 8
  • 47
  • 79
Mr. Jo
  • 4,946
  • 6
  • 41
  • 100

4 Answers4

3

You can use pure JavaScript to do this by just cloning the .element div using the cloneNode() method, assign new id and value to the clone div and finally append it back to the document using the insertBefore() method like this:

let x = document.querySelector(".element");

let y = x.cloneNode(true);

y.children[0].id = "test--2";
y.children[0].defaultValue = "";

x.parentNode.insertBefore(y, x.nextSibling);
<div class="wrapper">
    <div class="element">
        <input id="test--1" value="ABC"/>
    </div>
</div>

JSFiddle with the above code: https://jsfiddle.net/AndrewL64/jvc7reza/18/

AndrewL64
  • 15,794
  • 8
  • 47
  • 79
1

Based on this answer you could do like:

$('#cloneBtn').on('click', function() {

  // get the last input having ID starting with test--
  var $inp = $('[id^="test--"]:last');  // Or use :first if you need
  // Get parent element 
  var $div = $inp.closest('.element');
  // Create clone
  var $div_clone = $div.clone();
  // Retrieve number from ID and increment it
  var num = parseInt($inp.prop("id").match(/\d+/g), 10) + 1;
  // Generate new number and assign to input
  $div_clone.find('[id^="test--"]').prop({id: 'test--' + num, value: ''});
  // Insert cloned element
  $div.after($div_clone);   // Or use .before() if you need 

});
.element {
  padding: 10px;
  outline: 2px solid #0bf;
}
<button id="cloneBtn">CLICK TO CLONE</button>

<div class="wrapper">
  <div class="element">
    <input id="test--1" value="ABC" />
  </div>
</div>

Once done inspect the input elements to see the new IDs

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

Scrambled elements, retrieve highest ID, increment, clone, append.

If your numbered IDs are scrambled, we first need a way to retrieve the highest ID number. Here's an implementation in pure JavaScript:

function cloneElement () {
  
  const inpAll = document.querySelectorAll('[id^="test--"]');
  if (!inpAll.length) return; // do nothing if no elements to clone
  const maxID = Math.max.apply(Math, [...inpAll].map(el => +el.id.match(/\d+$/g)[0]));
  const incID = maxID + 1;
  const element = document.querySelector('.element'); // Get one for cloning
  const eleClone = element.cloneNode(true);
  const inpClone = eleClone.querySelector('[id^="test--"]');
  inpClone.id = 'test--'+ incID;
  inpClone.value = incID;              // just for test. Use "" instead
  document.querySelector('.wrapper').prepend(eleClone);
}


document.querySelector('#cloneBtn').addEventListener('click', cloneElement);
.element {
  padding: 10px;
  outline: 2px solid #0bf;
}
<button id="cloneBtn">CLICK TO CLONE</button>

<div class="wrapper">

  <div class="element">
    <input id="test--1" value="1" />
  </div>
  
  <div class="element">
    <input id="test--23" value="23" />
  </div>
  
  <div class="element">
    <input id="test--7" value="7" />
  </div>

</div>

Once done inspect the input elements to see the new IDs

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • 1
    I really like this but it's not resetting the content before appending it. Maybe it's a bug in your code? – Mr. Jo Dec 14 '19 at 18:43
0

I don't know what data you know, why you want to do such a thing but it can be done :-)

One way is like that:

const elemToCopy = document.getElementById("test--1").parentNode; // I assume you know id
const copiedElem = elemToCopy.cloneNode(true);

const newInput = copiedElem.querySelector("#test--1");
newInput.id = "test--2";
newInput.value = "";

elemToCopy.parentNode.append(copiedElem);

Let me know in a comment if something is not clear :-)

Adam Orłowski
  • 4,268
  • 24
  • 33
-1

Yes, use jQuery's .clone().

Here is an example that might be relevant to your situation:

let newElement = $('.element').clone();

newElement.find('input').attr('id', 'test--2').val('');

$('.wrapper').append(newElement);

Explanation

In the first line, we created a new cloned element by using jQuery clone().

Then, we found it's child input, changed it's ID and reset the val().

Finally, we found the .wrapper element and appended the new cloned element to it.

Alon Pini
  • 581
  • 1
  • 3
  • 19