Sinmok
Sinmok

Reputation: 656

jQuery adding elements to parent

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.

Example of desired result

Upvotes: 9

Views: 49228

Answers (5)

merv
merv

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>')
    );
});

Edit

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.

JSFiddle

Upvotes: 14

John Kalberer
John Kalberer

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

Nishu Tayal
Nishu Tayal

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

Nathan
Nathan

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.

Example.

Upvotes: 0

thecodeparadox
thecodeparadox

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

Related Questions