Lukas
Lukas

Reputation: 148

Append mustache templates in loop

I am trying to append the same mustache template several times but each time with different values that comes from php via ajax. The values are stored in an array.

Unfortunately each appended template includes the values from the last entry in the array.

If I add alert("test"); at the end of the loop it is working. Do I have to wait until the append-function is finished? If so, how can I do that?

Thanks!

$(document).ready(function postData() {
        var id = localStorage.getItem('user-id');
        var token = localStorage.getItem('user-token');
        var vars = "id=" + id + "&token=" + token;
        var hr = new XMLHttpRequest();
        var url = "../php/getUsers.php";

          hr.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                var data = JSON.parse(hr.responseText);

                for(var i=0;i<data.length;i++){

                        var templateData = {
                            name: data[i].name,
                            id: data[i].id

                        };
                      var id=templateData['id'];

                      $.get('templates/user.htm', function(templates) {

                            var template = $(templates).filter('#user-template').html();
                            $('#user-container').append(Mustache.render(template, templateData));
                        });
                 //alert("Test"); 
                 }
            }
        }
        hr.open("POST", url, true);
        hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        hr.send(vars);
    });

Upvotes: 0

Views: 2154

Answers (1)

ncardeli
ncardeli

Reputation: 3492

The problem is that when the callback function for the $.get call is invoked, templateData already changed in the next iterations of the for loop.

To avoid this common closure problem, you can do the following:

$.get('templates/user.htm', (function (templateData) {
    return function(templates) {
        var template = $(templates).filter('#user-template').html();
        $('#user-container').append(Mustache.render(template, templateData));
    }
})(templateData));

If you are using ES2015, you don't need to change the callback function, because you can use let instead of var to define the templateData variable:

let templateData = {
    name: data[i].name,
    id: data[i].id

};

...

$.get('templates/user.htm', function(templates) {
    var template = $(templates).filter('#user-template').html();
    $('#user-container').append(Mustache.render(template, templateData));
});

Upvotes: 1

Related Questions