Search code examples
javascriptjsonnode-red

How to convert a JSON tree to a dynamic HTML table


(First allow me to say that I'm just beginning to learn Node-RED concepts; I went through some beginners' guides at nodered.org, and now am trying to extend what I learned so far). I'm trying to build a flow that starts with a simple JSON tree like

[{"position":"1", "title":"element #1"},
{"position":"2", "title":"element #2"},
{"position":"3", "title":"element #3"}]

To build that treee I use a template node, property is set to msg.payload. The number of array elements (in theory) is dynamic. To make sure that this tree is true JSON I added a JSON node converting from String to JSON object.

Next I wish to parse that object into a dynamic html table. For this I used a JS function node that's looping through the object and embedding its elements into the according html elements like this:

var return="";
for(var i=0;i<=msg.payload.length-1;i++){
    var row=msg.payload[i];
    if(row){
        return+="<tr>";
        return+="<td>"+row.position+"</td>";
        return+="<td>"+row.title+"</td>";
        return+="</tr>";
    }else{
        return+="no object at index "+i.toString();
    }
}
msg.payload=return;
return msg;

The output of the function then should be passed into a 2nd template like this:

<html>
    <head></head>
    <body>
        <table border="1">
            <tr>
                <td>#</td>
                <td>Title</td>
            </tr>
            {{ payload }}
        </table>
    </body>
</html>

I would have expected that the function's result is inserted into the static table of my template, and that happens indeed but not the way I hoped: somehow the html elements that got created by my function are not recognized as what they shoud be; instead I see that they are rendered as

&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;

instead of

<tr><td>1</td>

etc.

Result is that the browser does not recognize those elements and prints them together with their contents outside my static table

Questions:

  • what do I need to do so that my 2nd template recognizes my computed string as a set of html elements?
  • or is this probably a concept not suitable for my purpose?

Solution

  • I'm assuming you are using handelbars for your templating engine. In that case use:

    {{{ payload }}}
    

    Instead of

    {{ payload }}
    

    However a more elegant approach would be this:

    <html>
        <head></head>
        <body>
            <table border="1">
                <tr>
                    <td>#</td>
                    <td>Title</td>
                </tr>
                {{#each payload}}
                  <tr><td>{{this.position}}</td><td>{{this.title}}</td></tr>
                {{/each}}
            </table>
        </body>
    </html>
    

    then just

    return msg.payload