Reputation: 2191
I'm new to jQuery and am trying to just create a load of simple test rows and be able to create new rows by clicking the add button and remove each row by clicking their corresponding 'delete' text. For some reason, whenever the first row is deleted, I can no longer add new rows.
Here's the HTML:
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='all'>
<button class='add'>Add</button>
<div class='row'>hi - <span class='del'>delete</span></div>
</div>
And the jQuery:
var row, add, rows;
$(document).ready(function(){
row = $('.row'); // problem? because it's not a clone?
add = $('.add');
rows = $('.row');
add.on("click", function(){
row.clone().appendTo($('#all')); // problem? because it's now gone?
rows = $('.row');
updateRows();
});
});
function updateRows() {
rows.on("click", ".del", function(){
$(this).parent().fadeOut(1000, function(){
$(this).remove();
});
rows = $('.row');
});
}
I've also made a CodePen demo if that helps. So my question is, why does the 'add' button stop working after the first row is deleted? I wonder whether once the first row is deleted, it can't be appended as the variable is then deleted, and if I'm right, how can you create a variable clone that stays even when it's deleted (if you know what I mean)?
Thanks for any help here - any explanations would be much appreciated.
Upvotes: 0
Views: 31
Reputation: 10765
If you delete the only row, there will be nothing inside of the variable row
and therefore cause an error when you call row.clone()
. You could set row = the html string of the row you wanted to .clone()
and instead append the row as html to your div
var row, add, rows;
$(document).ready(function(){
row = '<div class="row">hi - <span class="del">delete</span</div>'; // changed to html string to append to div
add = $('.add');
rows = $('.row');
add.on("click", function(){
$('#all').append(row);
rows = $('.row');
updateRows();
});
});
function updateRows() {
rows.on("click", ".del", function(){
$(this).parent().fadeOut(1000, function(){
$(this).remove();
});
rows = $('.row');
});
}
See updated codepen: (https://codepen.io/anon/pen/NeEbbL)
Upvotes: 1
Reputation: 28611
You can copy the outerHTML of the row so that it's always available. Using $(".row").first().html()
only copies the inner HTML (so doesn't include the class=row
part).
This gives you:
var row = $(".row").first().outerHTML(); // store first row
$('.add').on("click", function() {
$("#all").append(row);
});
Copy outerHTML taken from: https://stackoverflow.com/a/4180972/2181514
As you're using event delegation for the del button, you only need to call this once, giving:
(function($) {
$.fn.outerHTML = function() {
return $(this).clone().wrap('<div></div>').parent().html();
};
})(jQuery);
$(document).ready(function() {
var row = $(".row").first().outerHTML(); // store first row
$('.add').on("click", function() {
$("#all").append(row);
});
$(document).on("click", ".row>.del", function() {
$(this).closest(".row").fadeOut(1000, function() {
$(this).remove();
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='all'>
<button class='add'>Add</button>
<div class='row'>hi - <span class='del'>delete</span></div>
</div>
Updated codepen: https://codepen.io/anon/pen/qLQqJm
Upvotes: 2