-1

I have several divs in code. I need to update the html inside, based on API request. It works, but html doesn't refresh (i.e. if I get via API a new result, html remain same of first iterate, but in firebug I can read new HTML ready to inject in page).

$('div.show-gpio-state').each(function(i, obj) {
        var id_gpio = $(this).data('id-gpio');
        getGpioState(id_gpio,$(this));
        setInterval(function(){getGpioState(id_gpio,$(this))}, 5000);
    });

function getGpioState(id_gpio,box) {

    $.ajax(
            {   url: api_gpio_url+id_gpio,
                cache:false,
                success: function (result) {
                    box.html('');
                    var state = result;
                    var final_state = '';
                    if ( (state==='error') || (state==='') ) {
                        final_state = '<span class="text-danger"><i class="fa fa-fw fa-2x fa-exclamation-triangle"></i></span>';
                    } else {
                        if (state==1) {
                            final_state = '<p class="h2"><i class="fa fa-fire text-success"></i></p>';
                        } else {
                            final_state = '<p class="h2"><i class="fa fa-remove text-grey"></i></p>';
                        }
                    }
                box.html('');
                box.html(final_state);
                // here in console I have right final state for right box
                console.log(final_state);
                console.log(box);

            }
        });

}
sineverba
  • 5,059
  • 7
  • 39
  • 84
  • Why are you testing for failure in your success callback? Why not just accept the result and inject it where it should go and set up a second error callback? – Scott Marcus Nov 30 '16 at 19:02
  • Possible duplicate of [How does the "this" keyword work?](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – André Dion Nov 30 '16 at 19:18

2 Answers2

1

Change this

setInterval(function(){getGpioState(id_gpio,$(this))}, 5000);

to

setInterval(function(){getGpioState(id_gpio,$(this))}.bind(this), 5000);

or assign $(this) to variable and pass inside setInterval function

maheshiv
  • 1,778
  • 2
  • 17
  • 21
  • 1
    The reasons that works is the function scope of `this`, because inside the `setInterval` you defining a new function with it's own scope. So `this` will refer to the `setInterval`-function instead of jQuery `each` function – empiric Nov 30 '16 at 19:08
1

You could fix it like:

setInterval((function(_this){
  return function(){
    getGpioState(id_gpio,$(_this));
  };
}(this)), 5000);

The issue is related to how scope and this keyword works in JavaScript.

Or you could even simply use a variable:

$('div.show-gpio-state').each(function(i, obj) {
    var id_gpio = $(this).data('id-gpio');
    var $this = $(this);
    getGpioState(id_gpio,$this);
    setInterval(function(){getGpioState(id_gpio,$this)}, 5000);
});

To learn more about the issue you could read this post: Understand JavaScript’s “this” With Clarity, and Master It

Mehran Hatami
  • 12,723
  • 6
  • 28
  • 35