Reputation: 656
I'm having some trouble figuring out how to add elements to a parent object on a click event.
The result that i'm hoping to achieve is this:
<ul>
<li><button>B1</button>
<ul class="newul">
<li><button>B1.1</button>
<ul class="newul">
<li><button>1.1.1</button></li>
<li><button>1.1.2</button></li>
</ul>
</li>
<li><button>B1.1</button></li>
</ul>
</li>
<li><button>B2</button></li>
<li><button>B3</button></li>
</ul>
Let's say I click button B2. I want a new UL added to the parent LI of that button and then be able to add new LI elements to the newly created UL. I hope that makes sense!
So basically, click button, add new UL with class "newul" to the LI you're currently in -> add new LI's to that newly created UL.
The jquery I'm currently using is as follows:
$('button').click(function(){
//Get parent..
var parent = $(this).parent();
//Add a new UL to the parent and save it as newul
var newul = parent.add("ul");
//Add the class to the new UL
newul.addClass('newul');
//Add a new li to the new UL
newli = newul.add('li');
//Add a button to the new LI
newli.append('<button></button>');
});
Unfortunately, this is having completely undesired effects and sticks buttons everywhere all over the place. I'd appreciate any help you can offer.
Here's a visible example of what i'm after. The top part is the effect id like to achieve.
Upvotes: 9
Views: 49228
Reputation: 76720
Even though @am not i am has the correct code. There is no explanation of why your code fails, and I think that's the answer you are asking for.
There are several problems in your code:
First
//Add a new UL to the parent and save it as newul
var newul = parent.add("ul");
The 'ul'
is a selector and so is going to search the DOM for other <ul>
elements, rather than create a new one. Also, parent.add()
method is returning the parent
object, not the ul's that you selected.
Correct code:
//Add a new UL to the parent and save it as newul
var newul = $("<ul>").appendTo(parent);
Second:
//Add a new li to the new UL
newli = newul.add('li');
Same problem again, and since newul
is actually still the parent
you're getting all types of craziness. Also, you're missing a var
, but maybe I just don't get your closure.
Correct code:
//Add a new li to the new UL
var newli = $("<li>").appendTo(newul);
That's all. If you fix that in your code, it'll work.
However, unless you really need those references to persist, better performance is usually achieved if you pass the whole thing as a string:
$('button').click( function() {
$(this).parent()
.append(
$('<ul class="newul"><li><button></li></ul>')
);
});
And if you wanted all the new buttons to have the same functionality, use the on()
method and a class for your buttons:
$('body').on('click', 'button.ul-appending', function() {
$(this).parent()
.append(
$('<ul class="newul"><li><button class="ul-appending"></li></ul>')
);
});
You could change the 'body'
selector to something much more specific so this doesn't get queried on every click on your page. Just make sure to add the class ul-appending
to all the existing buttons that aren't generated by this handler.
Upvotes: 14
Reputation: 5790
One issue I see here is that the new buttons created will not have the click event bound to them. I fix this by using on
and setting the event as a delegate. In doing so I give the outer ul
an id
of container
. I also check to make sure you haven't already added a ul
element and append one if it isn't inside the li
. Here is a working example.
$('#container').on("click", "button.newbtn", function(){
var parent = $(this).closest('li');
var childUl = parent.children('ul');
if(childUl.length === 0) {
parent.append("<ul class='newul'></ul>");
childUl = parent.children('ul');
}
childUl.append($("<li><button class='newbtn'>" + $(this).html() + "." + (childUl.children().length + 1) + "</button></li>"));
});
Upvotes: 1
Reputation: 20830
Use .on function for dynamically added elements.
You can use something like this.
$(document).ready(function(){
i = 1;
$('body').on("click","button",function(event){
$(this).after('<ul class="newul"><li><button>TestButton'+i+'</button></li></ul>');
i++;
});
});
Here is the DEMO. Adjust button with your css and button values accordingly.
Upvotes: 0
Reputation: 7032
The issue here is that you're using .add() instead of .after().
.add()
adds the passed element to the current selection. .after()
adds the passed elements after the current selection.
Using .after()
, we can simplify your script into a nice little one-liner:
$('button').click(function(){
$(this).after('<ul class="newul"><li><button></button></li></ul>');
});
Since .after()
inserts content next to the current element, there's no need to get the .parent()
. .after()
can take a complete string of HTML, so there's no need to use jQuery to manipulate the class and add the child elements.
Upvotes: 0
Reputation: 87073
$('button').click(function(){
//Get parent..
var parent = $(this).parent();
//Add a new UL to the parent and save it as newul
var newul = $("<ul/>");
//Add the class to the new UL
newul.addClass('newul');
//Add a new li to the new UL
var newli = $('<li/>');
//Add a button to the new LI
newli.append('<button></button>');
// add ul to parent li
parent.append( newul.append( newli ) );
});
Upvotes: 0