0

I have a form where I add inputs dynamically. When I add a new input I increment a global id variable and concatenate it to the input's id so it will be unique. I also create a delete button for each input that should remove that input and himself (through removing the container <div> they are in). I do the remove process by adding an anonymous function to the delete button's click event via JQuery:

$('#deletebutton' + id).click(function(){
    $('#inputcontainer' + id).remove();
});

The only problem with this solution that it isn't work in the way I excepted it. When I click any of the delete buttons it will delete the last input container because when I click, it executes the anonymous function and evaluate the id variable at that time, so the selected id will be the last input's id. So always the last input container will be deleted.

Is there a way to rewrite this function so when I add it to the click event, than it will evaluate the id, inject it and handle the selection as if it had been written like #inputcontainer1, #inputcontainer2, etc.

I can make this by adding the function's body to the button's onclick() event:

var newbutton = '<button id="deletebutton' + id + '" type="button" onclick="javascript:$(\'#inputcontainer' + id + '\').remove();">x</button>';

But is there a way doing this with the JQuery click() way?

Nikos Grigoriadis
  • 2,912
  • 4
  • 22
  • 29
totymedli
  • 29,531
  • 22
  • 131
  • 165

3 Answers3

2

To answer the specific question, you'd have to dig the id out of the DOM:

$('#deletebutton' + id).click(function(){
    var id = $(this).attr("id").replace('deletebutton','');
    $('#inputcontainer' + id).remove();
});

You could also store it as data when you create the delete button:

<button data-id="1" id="deletebutton1">

$('#deletebutton' + id).click(function(){
    var id = $(this).data("id");
    $('#inputcontainer' + id).remove();
});

Note that in both of these cases, id is a string, not an integer.

Grim...
  • 16,518
  • 7
  • 45
  • 61
  • Exactly what I was going to write, to the letter. – Andy Aug 23 '13 at 11:16
  • @andy this is Stack Overflow, so I assume you're going to write it anyway? ;-) – Grim... Aug 23 '13 at 11:17
  • Wow this solution is even better than what I wanted to do. This way I doesn't even need to inject variable values. Your solution is much dynamic. The only problem is that you need to give a second argument to `replace()`, otherwise it will return `"undefined1"`, `"undefined2"`, etc. `$(this).attr("id").replace('deletebutton', '');` works perfectly. – totymedli Aug 23 '13 at 11:37
1

When I click any of the delete buttons it will delete the last input container [...]

If your 1st snippet is inside a loop, id probably isn't being scoped to each iteration. So, by the time one of the click() events is triggered and it's trying to use .remove(), id will have already been set to the last value given while looping.

You can use an IIFE to create an additional function scope for keeping a different id for each iteration (ref: closure).

/* loop */ {
    var id = ...;

    (function (id) {
        $('#deletebutton' + id).click(function(){
            $('#inputcontainer' + id).remove();
        });
    })(id);
}

Though, for future reference, ECMAScript 6 is adding block scoping which should allow for:

/* loop */ {
    let id = ...;

    $('#deletebutton' + id).click(function(){
        $('#inputcontainer' + id).remove();
    });
}
Community
  • 1
  • 1
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
0
$('#deletebutton' + id).click(function(){
    $(this).parent().remove();
});

If the container isn't a direct parent and doesn't have a class you could do:

$('#deletebutton' + id).click(function(){
    var idNum = $(this).attr("id").replace('deletebutton','');
    $("#inputcontainer"+idNum).remove();
});

If you've got appropriate classes (or can add them), this would be best:

$(document).on("click",".deleteButton",function() {
    $(this).parents(".inputContainer").remove();
});
MDEV
  • 10,730
  • 2
  • 33
  • 49