How to pass msg.payload to <script></script> in template node of node-red-dashboard 3.6.5?

How to pass msg.payload coming from function node to within html in template node of node-red-dashboard 3.6.5?

It is possible to handle msg.payload content as {{msg.payload}} in html body clause in the form of text. I would like to generate several divs in html body to have dynamic dashboard. I tried to handle generated divs as a string , though it is displayed as a text in the dashboard. I usually generate the dynamic content in script, thus I would like to handle the msg.payload there.

If you provide an simple example flow of what you are attempting, it would be simpler to show you where you may be going wrong.

I don't know what a "generated s" is but I think you have to build your html in a standard template node, which does understand mustache syntax, and pass it (somehow - not sure how) to the ui-template node.

sorry, I have edited

[
    {
        "id": "c72e2c75a7462599",
        "type": "tab",
        "label": "Flow 3",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "e019efc88a6cdd76",
        "type": "inject",
        "z": "c72e2c75a7462599",
        "name": "Trigger",
        "props": [
            {
                "p": "timer",
                "v": "true",
                "vt": "bool"
            }
        ],
        "repeat": "3",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 220,
        "y": 220,
        "wires": [
            [
                "4ae67db43e83cbdf"
            ]
        ]
    },
    {
        "id": "4ae67db43e83cbdf",
        "type": "function",
        "z": "c72e2c75a7462599",
        "name": "generate an array",
        "func": "if (msg.timer){\n    const x1 = Math. floor(Math. random()*100) + 1;\n    const x2 = Math. floor(Math. random()*100) + 1;\n    const y1 = Math. floor(Math. random()*100) + 1;\n    const y2 = Math. floor(Math. random()*100) + 1;\n    msg.payload = [{\"x\": x1, \"y\": y1},{\"x\": x2, \"y\": y2}]\n    return msg;\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 220,
        "wires": [
            [
                "14b55d239cac786e",
                "710808bde91989dc"
            ]
        ]
    },
    {
        "id": "14b55d239cac786e",
        "type": "ui_template",
        "z": "c72e2c75a7462599",
        "group": "8f98df76dce28bed",
        "name": "",
        "order": 1,
        "width": "24",
        "height": "10",
        "format": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Dynamic content</title>\n    <style>\n        .rectangle {\n            position: relative;\n            width: 1200px;\n            height: 600px;\n            background-color: lightgray;\n            border: 1px solid #000;\n        }\n    \n        .dot {\n            position: absolute;\n            width: 10px;\n            height: 10px;\n            background-color: red;\n            border-radius: 50%;\n        }\n    </style>\n</head>\n\n<body>\n    <div class=\"rectangle\">\n        <div id=\"container\"></div>\n    </div>\n    <script>\n        items = {{msg.payload}}// example [{\"x\":67,\"y\":12},{\"x\":12,\"y\":30}]\n        // Get the container element\n        let container = document.getElementById('container');\n\n        // Loop through the array and create divs\n        items.forEach(item => {\n            // Create a new div element\n            let div = document.createElement('div');\n    \n            // Set the class of the div\n            div.className = 'dot';\n    \n            // Set the position of the div\n            div.style.left = `${item.x}px`;\n            div.style.top = `${item.y}px`;\n    \n            // Append the div to the container\n            container.appendChild(div);\n        });\n    </script>\n</body>\n\n</html>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 640,
        "y": 220,
        "wires": [
            []
        ]
    },
    {
        "id": "710808bde91989dc",
        "type": "debug",
        "z": "c72e2c75a7462599",
        "name": "array",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 630,
        "y": 260,
        "wires": []
    },
    {
        "id": "8f98df76dce28bed",
        "type": "ui_group",
        "name": "Generate movement",
        "tab": "ea194238f31066a8",
        "order": 1,
        "disp": true,
        "width": "24",
        "collapse": false,
        "className": ""
    },
    {
        "id": "ea194238f31066a8",
        "type": "ui_tab",
        "name": "Home",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

Your ui_template appears to be a complete web page but the template is inserted into the existing web page so you probably don't want all the <html> and <head> stuff, just the contents of the <body>.

If you want a complete dynamic page without the additional stuff that comes with Dashboard and VueJS, you might be better off using UIBUILDER or straight http-in/-out nodes.

You would use the second example in the side bar help for ui-template. You can then watch for incoming msg.payload.
Example template. No html or body tags requiredd

<style>
        .rectangle {
            position: relative;
            width: 1200px;
            height: 600px;
            background-color: lightgray;
            border: 1px solid #000;
        }
    
        .dot {
            position: absolute;
            width: 10px;
            height: 10px;
            background-color: red;
            border-radius: 50%;
        }
</style>

    <div class="rectangle">
        <div id="container"></div>
    </div>
    
<script>
    (function(scope) {
        scope.$watch('msg', function(msg) {
            if (msg.payload) {
                items = msg.payload// example [{"x":67,"y":12},{"x":12,"y":30}]
                // Get the container element
                let container = document.getElementById('container');

                // Loop through the array and create divs
                items.forEach(item => {
                    // Create a new div element
                    let div = document.createElement('div');
    
                    // Set the class of the div
                    div.className = 'dot';
    
                    // Set the position of the div
                    div.style.left = `${item.x}px`;
                    div.style.top = `${item.y}px`;
    
                    // Append the div to the container
                    container.appendChild(div);
                });
            }
        });
    })(scope);
</script>

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.