Search code examples
javascripthtmlinnerhtmlappendchild

Javascript For loop appending child only appends first element, then throws error


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


Solution

  • 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.