48

I would like to dynamically add a button control to a table using jQuery and attach a click event handler. I tried the following, without success:

$("#myButton").click(function () {
    var test = $('<button>Test</button>').click(function () {
        alert('hi');
    });

    $("#nodeAttributeHeader").attr('style', 'display: table-row;');
    $("#addNodeTable tr:last").before('<tr><td>' + test.html() + '</td></tr>');
});

The above code successfully adds a new row, but it doesn't handle adding the button correctly. How would I accomplish this using jQuery?

5 Answers 5

64

Calling .html() serializes the element to a string, so all event handlers and other associated data is lost. Here's how I'd do it:

$("#myButton").click(function ()
{
    var test = $('<button/>',
    {
        text: 'Test',
        click: function () { alert('hi'); }
    });

    var parent = $('<tr><td></td></tr>').children().append(test).end();

    $("#addNodeTable tr:last").before(parent);
});

Or,

$("#myButton").click(function ()
{    
    var test = $('<button/>',
    {
        text: 'Test',
        click: function () { alert('hi'); }
    }).wrap('<tr><td></td></tr>').closest('tr');

    $("#addNodeTable tr:last").before(test);
});

If you don't like passing a map of properties to $(), you can instead use

$('<button/>')
    .text('Test')
    .click(function () { alert('hi'); });

// or

$('<button>Test</button>').click(function () { alert('hi'); });
Sign up to request clarification or add additional context in comments.

3 Comments

FWIW, I don't like the way you've done click as an extension to the element creation - I think .click() is more intuitive, and better documented.
Either way works just fine. I can show how do it with chaining as well.
it makes more sense now you've added the extra attributes
10

Quick fix. Create whole structure tr > td > button; then find button inside; attach event on it; end filtering of chain and at the and insert it into dom.

$("#myButton").click(function () {
    var test = $('<tr><td><button>Test</button></td></tr>').find('button').click(function () {
        alert('hi');
    }).end();

    $("#nodeAttributeHeader").attr('style', 'display: table-row;');
    $("#addNodeTable tr:last").before(test);
});

5 Comments

there's no need to .end() that chain.
It is. find('button') will return just button element, but you need whole tr>td>button structure :)
ah - I see - to ensure that the returned value is the <tr> itself? Useful :)
@Matt Ball: Why is a terminal end() ever necessary?
Oh, never mind. It's only useless at the end if you don't care about the returned value.
8

Your problem is that you're converting the button into an HTML snippet when you add it to the table, but that snippet is not the same object as the one that has the click handler on it.

$("#myButton").click(function () {
    var test = $('<button>Test</button>').click(function () {
        alert('hi');
    });

    $("#nodeAttributeHeader").css('display', 'table-row'); // NB: changed

    var tr = $('<tr>').insertBefore('#addNodeTable tr:last');
    var td = $('<td>').append(test).appendTo(tr);
});

Comments

0

You can either use onclick inside the button to ensure the event is preserved, or else attach the button click handler by finding the button after it is inserted. The test.html() call will not serialize the event.

Comments

0

You were just adding the html string. Not the element you created with a click event listener.

Try This:

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
</head>
<body>
    <table id="addNodeTable">
        <tr>
            <td>
                Row 1
            </td>
        </tr>
        <tr >
            <td>
                Row 2
            </td>
        </tr>
    </table>
</body>
</html>
<script type="text/javascript">
    $(document).ready(function() {
        var test = $('<button>Test</button>').click(function () {
            alert('hi');
        });
        $("#addNodeTable tr:last").append('<tr><td></td></tr>').find("td:last").append(test);

    });
</script>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.