0

I'm looping through a js object with a nested for loop, stated below, it appends the first element correctly, but then throws the following error: Can't set the property className of an undefined reference or empty reference. (not sure if exact error, translating from Dutch...)

function allVideos() {
    var sql = "SELECT videos.VideoName, videos.VideoPath FROM videos";
    var resultSet = db.query(sql, {json:true}); //returns: [{"VideoName":"timelapse aethon2","VideoPath":"videos\\Roermond Papier\\160424 Time laps Aethon2.avi"},{"VideoName":"timelapse aethon3","VideoPath":"videos\\Roermond Papier\\160424 Time laps Aethon2.avi"}]
    var parsed = JSON.parse(resultSet);
    var parsedlength = arrLenght(parsed);
    //alert(resultSet);
    for(var i = 0; i < parsedlength; i++) {
        var obj = parsed[i];
        //alert(i);
        var videoElement = document.getElementById("allVideos");
        for (var key in obj) {
            if(obj.hasOwnProperty(key)) {

                videoElement.appendChild(document.createElement('div'));
                videoElement.children[i].id='allVid' + i;
                videoElement.children[i].className='col-md-4 col-xs-12';
                //alert(typeof key)
                var card = document.getElementById('allVid' + i);
                alert(i);
                card.appendChild(document.createElement('div'));
                card.children[i].className='card card-block';
                card.children[i].innerHTML = "<h3 class='card-title'>" + obj['VideoName'] + "</h3><button class='btn btn-primary'>Selecteren</button>"
            }
        }
    }
}

[EDIT] added screenshot of how it looks

enter image description here

Grey
  • 877
  • 9
  • 29

2 Answers2

1

Your code has some significant logic issues. You're using nested loops, but appending to an element assuming that the outer loop counter will let you index into that element's children to get the element you just appended. Later, you try to get that same element again using getElementById. Then, you append a new element to your newly-created element, but try to access that new element using children[i] on the one you just created — at that point, the card element will only have a single child, so as of the second outer loop, it will fail.

createElement returns the element to you, so there's no reason at all to try to access it via children[i] (either time) or getElementById.

See comments:

function allVideos() {
    var sql = "SELECT videos.VideoName, videos.VideoPath FROM videos";
    var resultSet = db.query(sql, {json:true});
    var parsed = JSON.parse(resultSet);
    var parsedlength = arrLenght(parsed);
    for(var i = 0; i < parsedlength; i++) {
        var obj = parsed[i];
        //alert(i);
        var videoElement = document.getElementById("allVideos");
        for (var key in obj) {
            if(obj.hasOwnProperty(key)) {
                // Create the card, give it its id and class
                var card = document.createElement('div');
                card.id='allVid' + i;
                card.className='col-md-4 col-xs-12';

                // Create the div to put in the card, give it its class and content
                var div = document.createElement('div');
                card.appendChild(div);
                div.className='card card-block';
                div.innerHTML = "<h3 class='card-title'>" + obj['VideoName'] + "</h3><button class='btn btn-primary'>Selecteren</button>"

                // Append the card
                videoElement.appendChild(card);
            }
        }
    }
}

Side note: arrLenght looks like a typo (it should be th, not ht), but moreover, there's no reason to use a function to get the length of an array; it's available via the array's length property: parsedLength = parsed.length.

Side note 2: You may find these ways of looping through arrays useful.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • oh, wow, I realise now how stupid that logic was indeed, your answer helped, though there is one very minor error in it, `videoElement.appendChild(card)` shouldn't be in the nested for loop, since this will cause doubles, instead, I put it in the 1st for loop. – Grey Nov 04 '16 at 09:09
  • @Luuk: If `videoElement.appendChild(card)` shouldn't be in the inner loop, we probably need to adjust the logic creating `card`...? – T.J. Crowder Nov 04 '16 at 09:15
  • for some reason it works perfectly with `videoElement.appendChild(card)` outside of the inner loop – Grey Nov 04 '16 at 09:40
0

Your problem is the if within the nested for:

 if(obj.hasOwnProperty(key)) { ...

The variable i is increased even if the property is not "owned" (when the if condition returns false), so next time that the condition is true, i is out of bounds.

Pablo Lozano
  • 10,122
  • 2
  • 38
  • 59
  • No, that's in the inner loop. It's true using `i` for indexing into `children` is a problem, but the main problem is trying to use it to index into an element that by definition only has one child. – T.J. Crowder Nov 04 '16 at 09:04