简体   繁体   中英

Inject JavaScript variable as value in anonymous function

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?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM