1

I have multiple function objects declared from the same function that deal with their own tables with dynamically added rows. I need to have a delete button of some kind for each row. Since there can be multiple of these objects, the row must know what object it is a part of, and the object could be nested in some arbitrary scope inside other objects (and out of reach of some arbitrary function declaration, I think?), the typical solution of an onClick referencing some other javascript function doesn't seem sufficient. I've got a setup using delegate to catch the click, but I'm not sure where to go from there. Here's some example code:

function testobject() {
 //other stuff

 $stateadd.click(function() {
  if ($stateselect.val() in states) { //already in array

  } else {
   $temp = $("<tr><td nowrap>" + USStates[$stateselect.val()].Name + "</td><td><input type=\"button\" class=\"testthing\" value=\"Remove\" /></td>").appendTo($selectedstates);
   $temp2 = $temp.find('.testthing');

   $temp.delegate($temp2, 'click', function(e) {
    //how to know what row to delete?  how to know which object the row is in?
    alert($(e.target).attr('class')); //returns proper class, so I can get the button object itself
   });

   states[$stateselect.val()] = $temp;
  }
 });

 //other stuff
}

To be clearer, I need two things in the click event: the testobject instance that made the row, and the $stateselect.val() id associated with that row. I can't just delete the row tr/td tags, I need to have it removed from the states object as well.

6
  • "the typical solution of an onClick referencing some other javascript function doesn't seem sufficient." Why not? That's how I would do it. It's not hard to determine where the button is when the click event is fired. Commented Feb 27, 2012 at 18:45
  • @Diodeus I assume they want to avoid defining event handlers using inline attributes on their elements, which definitely isn't a bad thing. Besides, there's not going to be much difference in what the function does so how it's bound to the event shouldn't matter. Commented Feb 27, 2012 at 18:49
  • Because I need to get the instance of testobject that made the row, and the $stateselect.val() that was associated with the row when I made it. How can I obtain that? Commented Feb 27, 2012 at 18:49
  • I agree. Using .on() would be a good choice for this solution. Commented Feb 27, 2012 at 18:51
  • You can store the value of $stateselect.val() as data in the element itself: $(this).data('stateselect',$stateselect.val()) and read it back later. Commented Feb 27, 2012 at 18:54

2 Answers 2

3

Use this to refer to the element which is clicked and then you can find the corresponding parent tr element using jQuery closest() method.

Also the first argument of delegate is the selector on which the delegated event should work. You were passing a jQuery object so it didn't work. Try this.

$('tableSelector').delegate('.testthing', 'click', function(e) {
    //Here "this" will point to the remove button.

    var $tr = $(this).closest('tr');//this will give you the corresponding row  
});

jQuery closest() gets the first element that matches the selector, beginning at the current element and progressing up through the DOM tree.

If you are using latest jQuery ver(1.7+) you can use on method.

$('tableSelector').on('click', '.testthing', function(e) {
    //Here "this" will point to the remove button.

    var $tr = $(this).closest('tr');//this will give you the corresponding row  
});

Note: You should keep this code outside testobject method because you don't need to add delegate or on everytime you call testobject method.

Update: Based on the comments

Add a data attribute to the input remove button with stateselect value.

$temp = $('<tr><td nowrap>' + USStates[$stateselect.val()].Name + '</td><td><input type="button" data-stateid="' + $stateselect.val() + '" class="testthing" value="Remove" /></td>').appendTo($selectedstates);

Js change

$('tableSelector').delegate('.testthing', 'click', function(e) {
    //Here "this" will point to the remove button.

    var sateId = $(this).data('sateid');
    var $tr = $(this).closest('tr');//this will give you the corresponding row  

    //Here you can access states[stateId] and do what you want
});
Sign up to request clarification or add additional context in comments.

8 Comments

In case you missed it, $(this) in context of delegate is what threw the click event. In this case your button. Also notice how he uses closest instead of parent().parent() or parents() because it is more efficient.
I can't just remove the row tr, I need to remove its entry from the states object. That requires me to have the correct instance of testobject and the $stateselect.val() that was inputted as the key value for the states object.
@user173342 - You can find the stateselect value using $tr.find('td:first').text()
That value is an index, but the value in the td is a string from an array that was accessed from that index. Also, alone that value is worthless to me, I need to be able to access the states object in some instanced testobject, then use that index value as the key to remove the entry from the states object.
While appending the remove button you can add a data-attribute to input element and then retrieve it inside click handler. Use that as key and remove the entry from states object.
|
0

"how to know what row to delete?"

you can finding the nearest <tr>

like $(this).closest('tr') and that will be the row to delete.

simply add to the end of that line

slideUp('slow', function() { 
    // now that you have slided Up, let's remove it from the DOM
    $(this).remove(); 
});

so, you could simply remove the click part and add this:

$(document).on('click', '.testthing', function(e) {
    alert($(e.target).attr('class'));

    var tr = $(this).closest('tr');
    tr.slideUp('slow', function() { 
        // now that you have slided Up, let's remove it from the DOM
        $(this).remove(); 
    });
});

4 Comments

$('.testthing').on() is not going to work. '.testthing' is added dynamically.
true ... was talking with the wife and on keyword was been added :)
live is depricated from latest version(1.7+) onwards, worth making a note of it.
so, that why I had written on... even without thinking I can write good code :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.