Firebase Javascript Read From Database and Insert Each key into HTML

I am working on a Javascript project and am trying to read all the keys in my firebase database and inserting each and every entry into its own HTML heading. Although I have run into a problem where it is not working. What should I do? Here is the code.

function comment(){
    x = document.getElementById("comment").value;
    writeUserData(x);

}


message_id = 0;
function writeUserData(words) {
    database.ref('comments/' + String(message_id)).set({
        comment: words,
    });

    message_id ++;
}

function readComments(){
    var children;
    database.ref("comments/").on("value", function(snapshot) {
        children = snapshot.numChildren();
    })

    for (i = 0; i < children; i ++){
        database.ref('comments/' + String(i)).on("value", function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
            var data = childSnapshot.val();

            //create html elements
            new_comment = document.createElement("H");
            new_comment.innerHTML = data;
            document.getElementById("comment_div").appendChild(new_comment);
            document.getElementById("comment_div").appendChild(document.createElement('br'));
        });
        });
    }
}

Also, I am new to databases. So if there is perhaps a better way to write this code, please let me know. Thanks!

Answer

Data is loaded from Firebase (and most modern cloud APIs) asynchronously. While that is happening, your main code continues to execute.

By the time your for (i = 0; i < children; i ++){ now runs, the children = snapshot.numChildren() hasn’t executed yet, so children has no value and the loop never enters.

The solution is always the same: any code that needs the data to the database, needs to be inside the callback that gets executed when the data has loaded.

So the simple solution is to move that code into the callback:

database.ref("comments/").on("value", function(snapshot) {
    children = snapshot.numChildren();
    for (i = 0; i < children; i ++){
        database.ref('comments/' + String(i)).on("value", function(snapshot) {
          snapshot.forEach(function(childSnapshot) {
            var data = childSnapshot.val();

            //create html elements
            new_comment = document.createElement("H");
            new_comment.innerHTML = data;
            document.getElementById("comment_div").appendChild(new_comment);
            document.getElementById("comment_div").appendChild(document.createElement('br'));
          });
        });
    }
})

But I don’t think you even need the nested on() call here, as all data is already loaded as part of database.ref("comments/").on("value". All you need to do is loop over it in the callback, which should look something like:

database.ref("comments/").on("value", function(commentsSnapshot) {
    commentsSnapshot.forEach(function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
            var data = childSnapshot.val();

            //create html elements
            new_comment = document.createElement("H");
            new_comment.innerHTML = data;
            document.getElementById("comment_div").appendChild(new_comment);
            document.getElementById("comment_div").appendChild(document.createElement('br'));
        });
    });
})

Leave a Reply

Your email address will not be published. Required fields are marked *