0

I am trying to refresh an if statement inside a function but its giving me an error

cannont read property of status

$.getJSON("<url>/clients.json", function(data) {
    var tr;
    for (var i = 0; i < data.length; i++) {
        tr = $('<tr/>');
        tr.append("<td>" + data[i].client +  "</td>");
        $('table').append(tr);

        var refresh = function() {
            if (data[i].status == "up") {
                $('td', tr).css ('background-color', '#88d066');
            } else {
                $('td', tr).addClass("statusHOSTDOWN");
            };
        }; 
        setTimeout(refresh, 5000);
    }
});

JSON example:

[{
    "client": "client1",
    "ip": "127.0.0.1",
    "status": "up"
}, {
    "client": "client2",
    "ip": "127.0.0.2",
    "status": "up"
}]

What would be the best way to rerun the if statement and update table color with new information from JSON without running the whole function inside setTimeout. Because running the whole function inside seTimeout just appends more table at the bottom of the existing table without replacing it with new information.

bran
  • 167
  • 1
  • 3
  • 12
  • What about this ,($.getJSON("/clients.json") html tag – Muhammed Albarmavi Aug 11 '16 at 09:18
  • By the time the refresh function is called, `i` will be `data.length` - and therefore `data[i]` is undefined – Jaromanda X Aug 11 '16 at 09:18
  • I'm unsure what you're asking here. Why can't you do away with the `setTimeout`, and have everything executed inside the loop directly? Regardless, the error you're probably getting is "cannot read property status of undefined", because your `[i]` inside the setTimeout handler will be `data.length`, because of [the closure-problem](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). – Matt Aug 11 '16 at 09:20
  • update with JSON format. – bran Aug 11 '16 at 09:24
  • Concept of your code is wrong, I cannot conclude what you want to do. Defining functions within a loop is generally not acceptable, neither is using the loop's iterator in a time delayed function calls. – Dellirium Aug 11 '16 at 09:25
  • Maybe refactor the code into three functions: trExists(), updateTr(), insertTr(). Then the callback can iterate over each item in data, (psuedo-code)... if trExists(client) then updateTr(client, status) else insertTr(client, status). Also maybe use class names like 'status-up' and 'status-down' and use jQuery to switch between the two using the value of data[i].status. E.g. `$(tr).removeClass('status-up status-host-down').addClass('status-' + status)` – Andy Taw Aug 11 '16 at 09:33

2 Answers2

0

First make sure by debugging you 'data' parameter indeed has a property status, if so, Extract the value of the data[i] to a variable before the function var refresh is declared.

var myDataStatus = data[i].status;
var refresh = function() {...

And inside the if refer to the "up" directly from myDataStatus.

Matt
  • 74,352
  • 26
  • 153
  • 180
acabra85
  • 369
  • 4
  • 13
-2

Can you please try this code :

function refresh(statusVal, trObj){
    if(statusVal == "up")
    {
        $('td',trObj).css ('background-color', '#88d066');
    } else {
        $('td',trObj).addClass("statusHOSTDOWN");
    };
}

$.getJSON("<url>/clients.json",
function (data) {

    var tr;
    for (var i = 0; i < data.length; i++) {
        tr = $('<tr/>');
        tr.append("<td>" + data[i].client +  "</td>");
        $('table').append(tr);
    setTimeout(function(){refresh(data[i].status, tr);}, 5000);
    }

});
  • getting `Cannot read property 'status' of undefined`. – bran Aug 11 '16 at 09:23
  • Can you please check is data have property status in it.. Please write the console.log(data[i]) in for lop. And then check in console what it is printing – robinbansalsolutions Aug 11 '16 at 09:24
  • This won't solve the closure problem. You instead need something like `setTimeout(refresh(i, tr), 5000);` and `function refresh(statusVal, trObj) { return function () { if(statusVal == "up") { $('td',trObj).css ('background-color', '#88d066'); } else { $('td',trObj).addClass("statusHOSTDOWN"); }; }; }`. See https://jsfiddle.net/u9t2wdt2/ vs https://jsfiddle.net/u9t2wdt2/1/. – Matt Aug 11 '16 at 09:25
  • @robinbansalsolutions from cosole.log I am getting out of jason data as: `Object {client: "clientname", ip: "", status: "up"}` – bran Aug 11 '16 at 09:30
  • @Matt I tried your example, while it didn't give any error, it didn't also give any output. `console.log(data[i].status);` didn't return anything. I assigned data variable as `var data = $.getJSON("/clients.json");` – bran Aug 11 '16 at 09:49
  • @bran: That will not work because the `$.getJSON` request completes asynchronously. You need something like https://jsfiddle.net/u9t2wdt2/2/ to solve your closure problem; but this does not solve your question "*What would be the best way to rerun the if statement and update table color with new information from JSON without running the whole function inside setTimeout*", for which we need you to update your question to be more clear on. – Matt Aug 11 '16 at 09:53