1

I have a button that when clicked dynamically inserts a new row into a table. I want to be able to remove rows from this table, so I'm trying to use jQuery's .on() function to attach a click handler to a span element at the end of each row.... which works fine, except that when I click on the span to remove a single item, the click event is called for all items in the table.... and they're all removed. How do I hook it up so it calls just the row I clicked on handler? Here is my code:

Here is the js:

$("#milestonesList").on('click', 'span[id*="tempmilestone"]', function (e) {
        $(this).each(function () {
            $('span[id*="tempmilestone"]').each(function () {
                alert("ON: " + $(this).attr("idx"));
                _milestones = _milestones.slice(parseInt($(this).attr("idx"), 10));
                buildMilestoneOutput(milestonesList);
            });
        });
    });

Now no matter what row I click on, every row's click event is fired. What am I doing wrong?

I have tried this numerous ways, without the .each() functions and still it fires for every row in the table. Maybe if I show the rest of the code it would help:

Here is the buildMilestoneOutput function that gets called at the end:

function buildMilestoneOutput(container) {
    container.innerHTML = "";
    alert("Length: " + _milestones.length);
    var s = "<table id='testscroll' style='width: 690px; padding: 10px;'><tr><td style='font-weight: bold;'>Title</td><td style='font-weight: bold;'>Description</td><td style='font-weight: bold;'>DueDate</td></tr>"
    for (var i = 0; i < _milestones.length; i++) {
        s += "<tr><td style='width: 300px; padding-bottom: 10px;'>" + _milestones[i].Title + "</td><td style='width: 350px; padding-bottom: 10px;'>" + _milestones[i].Description + "</td><td style='width: 30px; padding-bottom: 10px;'>" + _milestones[i].Name + "</td><td><span idx='" + i + "' style='margin-left: 5px; cursor: pointer;'  id='tempmilestone'>remove</span></td></tr>";
    }
    s += "</table>";
    container.innerHTML = s;
}

this original gets called when a user clicks an Add Milestone button:

$("#lbAddMilestone").click(function () {
       
        milestonesList.innerHTML = "";
        var newMilestone = new GoalMilestone();
        newMilestone.Title = "New Milestone";
        _milestones.push(newMilestone);
        buildMilestoneOutput(milestonesList);
        wireupMilestoneDeletes();
        
        return false;
    });

And here is the wireupMilestoneDeletes:

function wireupMilestoneDeletes() {


    $("#milestonesList").on('click', 'span[id*="tempmilestone"]', function (e) {
        alert("ON: " + $(this).attr("idx"));
        _milestones = _milestones.slice(parseInt($(this).attr("idx"), 10));
        buildMilestoneOutput(milestonesList);
    });
}
8
  • 2
    I would remove lines 2,3,7,8 from that code. Commented Oct 22, 2012 at 13:53
  • 1
    @Batman true, i didn,t even noticed second each Commented Oct 22, 2012 at 13:55
  • Basically your code says: "If a click happens in one of the items, loop through all the items and run this code for each of them", when you intended it to say: "If a click happens run this code for the specific item clicked" -> drop the eachs, $(this) already holds the item clicked. Commented Oct 22, 2012 at 14:09
  • 1
    You have multiple <span> elements with the same id because of <span idx='" + i + "' style='margin-left: 5px; cursor: pointer;' id='tempmilestone'> which can cause all sort of mumbo-jumbo. Try editing so it is id='tempmilestone"+i+"', then you increment the id and the selector with [id*='tempmilestone'] should still work Commented Oct 22, 2012 at 14:23
  • Ok...so you're saying the only change I should have to make is to make the span id unique? The wireupMIlestoneDeletes() function above should be fine as is and only fire the span that was clicked..right? Commented Oct 22, 2012 at 14:32

3 Answers 3

2

You don't need an each loop, let alone two. You're binding the click event to any of the <span>s that have an id containing "tempmilestone" and running the handler for the click of the specific <span> that was clicked. Therefore, this should suffice:

$("#milestonesList").on('click', 'span[id*="tempmilestone"]', function (e) {
    alert("ON: " + $(this).attr("idx"));
    _milestones = _milestones.slice(parseInt($(this).attr("idx"), 10));
    buildMilestoneOutput(milestonesList);
});
Sign up to request clarification or add additional context in comments.

2 Comments

That code does the exact same thing....I'm getting an alert for each row in the table with that rows idx value showing up....
check out my latest comment on the question, it might help
1

Ok...so I figured it out. I moved the wireupMilestonesDelete() function outside of the AddButton click event, to just underneath the $(document).ready function and it's now working. I was adding a new click event to each row, after each new row insertion. Glad that's over! :)

Comments

0

You are using double each loop that doesn't make sense here. At least, not something i understand...

Try this instead:

$("#milestonesList").on('click', 'span[id*="tempmilestone"]', function(e) {
    $(this).each(function() {       
            alert("ON: " + $(this).attr("idx"));
               //(.......)    
    });
});​

jsfiddle

Comments

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.