Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"i" value in JavaScript for loop is not being recognized in a jquery function

I'm using jQuery and ajax to open a bootstrap modal window. My code works perfectly when not in a loop, and my content is displayed appropriately in the modal window. But I have five modals on the page, and naturally I'd like to use a for loop so I don't repeat my code five times.

It seems like a no-brainer to write a for loop to execute the code five times, but somehow, there is a problem, and when I put the code into a for loop, the modal content will not show in the opened window.

Here is code that works how I need it, so the modal content from my modal1.php file shows in a modal popup window. Notice that the i variable is used three times; once in the jQuery selector, and twice in the $.ajax(...) area:

var i = 1;

$('#modal' + i).on('show.bs.modal', function(e) {
    var id = e.relatedTarget.dataset.id;
    $.ajax({
        type:'post',
        url:'modals/modal' + i + '.php',
        data:{id:id},
        success:function(data){
            $('#modal' + i).html(data);
        }
    });
});

This code below uses the variable i the exact same way as the code above. However, with the code below, the modal1.php content does not show (nor do any of the other files named 'modal[i].php'). Instead, only a blank dark background appears when they are opened.

for (i = 1; i < 6; i++) {
    $('#modal' + i).on('show.bs.modal', function(e) {
        var id = e.relatedTarget.dataset.id;
        $.ajax({
            type:'post',
            url:'modals/modal' + i + '.php',
            data:{id:id},
            success:function(data){
                $('#modal' + i).html(data);
            }
        });
    });
}

So I don't understand why the $.ajax() area of the code won't recognize the i variable in the for condition, but it will recognize it in the initial jQuery selector $('#modal' + i), which I've tested and found to be true. Is there a way I can write this loop so that the ajax area will recognize the i variable? Or is there a mistake in my code that I'm overlooking?

Incidentally, I've noticed that similar questions have been asked, but they have been downvoted for not being clearly written. I've read them all, and they don't answer the question that I have today.

like image 328
Mark Avatar asked Oct 27 '17 16:10

Mark


People also ask

Can we use for loop in jQuery?

You can use a JavaScript for loop to iterate through arrays, and a JavaScript for in loop to iterate through objects. If you are using jQuery you can use either the $. each() method or a for loop to iterate through an array.

What is '$' in jQuery?

$ sign is just a valid javascript identifier which is used as an alias for jQuery. Prototype, jQuery, and most javascript libraries use the $ as the primary base object (or function). Most of them also have a way to relinquish the $ so that it can be used with another library that uses it.

How FOR loop is executed in JavaScript?

To execute this loop, the Start condition is checked. This is usually the initial value where the counting should start. Next, the Condition is tested; this test determines whether the loop should continue. If the test renders a true result, then the Expression is used to modify the loop and the Statement is executed.

Can we return value in for loop in JavaScript?

The return statement immediately exits a function, returning the value of the expression that follows it. If you use a return statement in a loop without some sort of conditional like that it will preform the first pass and then exit. You need to collect them in a variable and return the variable after the loop.


2 Answers

The problem here is that you are (unintentionally) referencing a variable (i) via a closure.

Since scope is dictated by function in JavaScript, wrap your on usage with another (immediately invoked) function so a unique i is saved:

for (i = 1; i < 6; i++) {
    (function() {
        var iModalNumber = i;
        $('#modal' + iModalNumber).on('show.bs.modal', function(e) {
            var id = e.relatedTarget.dataset.id;
            $.ajax({
                type:'post',
                url:'modals/modal' + iModalNumber + '.php',
                data:{id:id},
                success:function(data){
                    $('#modal' + iModalNumber).html(data);
                }
            });
        });
    }());
}

The reason that these questions get down-voted so much is because issues/misunderstanding of closures is so common. It is admittedly a difficult concept to grasp, and your question was well written.

More information: How do JavaScript closures work?

like image 186
Jonathan.Brink Avatar answered Oct 13 '22 09:10

Jonathan.Brink


You could probably do this without using loop but using jQuery .each() and adding value attributes to your html elements. Warning... untested code ahead.

    jQuery('.modal').each(function(){               // use a class instead of an id
        $(this).on('show.bs.modal', function(e) {    //use $(this) to target
            var i = $(this).val();                   // get the value id            
            var id = e.relatedTarget.dataset.id;    // do your code
            $.ajax({
                type:'post',
                url:'modals/modal' + i + '.php',
                data:{id:id},
                success:function(data){
                    $('#modal' + i).html(data);
                }
            });
        });
    });
like image 31
Derek Nolan Avatar answered Oct 13 '22 11:10

Derek Nolan