node-red dashboard template

1,852 views
Skip to first unread message

nakia....@westrac.com.au

unread,
Jan 15, 2018, 3:27:08 PM1/15/18
to Node-RED
Hi All,

After doing a bit of experimenting with the dashboard node I was surprised to find that the form doesn't seem to allow you to set the input fields value via an input (inject for example).
Can anyone my findings are correct? Am I missing something..

If so, is the typical work around for this, creating your own form in the template node?
Would anyone have a basic working example of a template form that accepts data in (sets the value of the inputs) and sends data when its submitted (sends a msg.payload object).

.




nakia....@westrac.com.au

unread,
Jan 15, 2018, 3:29:44 PM1/15/18
to Node-RED
Oh, I should have mentioned. If I need to roll my own form in the template node, the example I would be looking for would be based on Angular Material if possible??

David Caparrós

unread,
Jan 15, 2018, 3:44:30 PM1/15/18
to Node-RED

Maybe you can try to set he input as a global variable first and then on you template you can get the value to work with it.


Regards 

Dave C-J

unread,
Jan 15, 2018, 4:07:14 PM1/15/18
to node...@googlegroups.com
Indeed the form currently doesn't support that. We'd be quite happy
for a PR if anyone was interested in looking at adding it.
Alternatively you can indeed us the ui_template as you suggest. Or
build one out of other existing elements - and then use a join node
(or custom function) to join the elements back into a single message
when a button is clicked.

nakia....@westrac.com.au

unread,
Jan 15, 2018, 4:10:46 PM1/15/18
to Node-RED
Thanks for the reply.

There is a small example in the info section that kind of eludes to being able to access the msg object but it doesn't actually provide an example utilizing an input element/form.

<div layout="row" layout-align="space-between">
    <p>The number is</p>
    <p ng-style="{color: (msg.payload || 0) % 2 === 0 ? 'green' : 'red'}">
        {{(msg.payload || 0) % 2 === 0 ? 'even' : 'odd'}}
    </p>
</div>

nakia....@westrac.com.au

unread,
Jan 15, 2018, 4:12:33 PM1/15/18
to Node-RED
Thanks for the reply.

Extending dashboard is well beyond my capability level.

Would you know of a working example using the template node I could look at?

steve rickus

unread,
Jan 15, 2018, 4:16:42 PM1/15/18
to Node-RED
I've had several debates with the node-red guys (well, mostly dceejay) on whether it would be helpful to enable this kind of behavior. I think I've come to see the light in a couple ways -- namely, that pattern of collecting a bunch of data in the client, and sending them all on submit, is a bit old-fashioned. Instead of holding user-entered info in the dom, widgets in the client browser framework (like angular md) modify an in-memory object model. Individual widgets (or even mouse/dom/browser/timer events) can keep their state synched with the back-end server, which can then react with ui updates before the whole form is submitted, making for a more dynamic user experience.

There have been many examples of angular templates posted on this mailing list, and on the flows.nodered.org site. You can use the built-in scope.send(msg) function to return data to the node-red flow. This object will be passed out of the ui_template node to any downstream nodes. At that point, you could use a join or function node to wait for all inputs before sending the msg on.

In case you haven't looked at it yet, there is also an alternative to the angular dashboard, called ui_builder. It's basically a websocket enabled msg passing framework ready for connecting to whatever client library you want to use (React, Riot, Moon, Marko, D3, Vue, etc). Of course, it's much more low level than using the dashboard ui, but it could be a good way to integrate node-red flows on the back-end into an existing front-end application.

nakia....@westrac.com.au

unread,
Jan 15, 2018, 4:25:59 PM1/15/18
to Node-RED
Thanks so much for this reply.

I did see UI Builder last night but it seems a little complex for my somewhat basic needs.

To be honest, I don't really need to even use a form (to your point). There are only really 10-15 parameters I need configurable from the front end.
Things such as directories, delay values etc.

I'll have a dig around an see what examples I can find. My search last night didn't return too much.

steve rickus

unread,
Jan 15, 2018, 5:02:35 PM1/15/18
to Node-RED
I've not used it myself, but there is the angular submit directive...

I just wish the ui_form was NOT implemented as a node, but as an adhoc way of grouping ui_* widgets. What does that mean? Well, the dashboard already has "tabs" representing pages and "groups" as content blocks, both of which affect the layout on the page. I'm thinking we could include a "form" element (essentially a container with a submit button) anywhere on the page, then any other ui_* nodes placed underneath that form would be sent as a single msg object. In fact, that could be implemented as a checkbox option on the existing "groups" (or perhaps just the existence of the ui_form button within a dashboard group would trigger the same behavior?). In my mind, the major change would be that there would be no additional UI layout provided by the ui_form node itself -- it would just logically link the inputs together and provide a way to send them as a single msg.

Of course, this is very low priority right now, but I may be able to take a whack at coding a solution -- so if anyone has a strong feeling on how to implement it, please reply.
--
Steve

nakia....@westrac.com.au

unread,
Jan 15, 2018, 5:18:30 PM1/15/18
to Node-RED
I've just found the example below that gives me a pretty good start.

Its of the non form model, which probably works okay for my specific application.

Would be good if I could get it to only send the message on field leave (not change)
 

On Tuesday, January 16, 2018 at 7:27:08 AM UTC+11, nakia....@westrac.com.au wrote:

nakia....@westrac.com.au

unread,
Jan 15, 2018, 10:12:00 PM1/15/18
to Node-RED
Hi All,

So I have a rough example flow that seems to be doing what I need for now.
Flow below for anyone that is interested.

[
    {
        "id": "b4c0cd5a.eecca",
        "type": "tab",
        "label": "Commands",
        "disabled": false,
        "info": ""
    },
    {
        "id": "4367b9e1.37ef68",
        "type": "ui_template",
        "z": "b4c0cd5a.eecca",
        "group": "e590899c.be8a18",
        "name": "App Settings",
        "order": 13,
        "width": "0",
        "height": "0",
        "format": "<md-input-container>\n    <label>Data Directory</label>\n    <input name=\"data_dir\" ng-model=\"msg.payload.data_dir\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n</md-input-container>\n<md-input-container>\n    <label>Arch Directory</label>\n    <input name=\"arch_dir\" ng-model=\"msg.payload.arch_dir\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n</md-input-container>\n<md-input-container>\n    <label>File Retention Duration (Days)</label>\n    <input name=\"retention_dur\" ng-model=\"msg.payload.retention_dur\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required type=\"number\" step=\"any\" name=\"rate\" min=\"1\" max=\"31\">\n</md-input-container>",
        "storeOutMessages": true,
        "fwdInMessages": false,
        "templateScope": "local",
        "x": 790,
        "y": 60,
        "wires": [
            [
                "d05e321b.82a98",
                "b0a4d18d.39aa8"
            ]
        ]
    },
    {
        "id": "d05e321b.82a98",
        "type": "file",
        "z": "b4c0cd5a.eecca",
        "name": "",
        "filename": "config.json",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "x": 1090,
        "y": 80,
        "wires": []
    },
    {
        "id": "56d75330.2c8aac",
        "type": "file in",
        "z": "b4c0cd5a.eecca",
        "name": "",
        "filename": "config.json",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "x": 290,
        "y": 80,
        "wires": [
            [
                "7c15aa15.3ac984"
            ]
        ]
    },
    {
        "id": "cacc4c84.a675e",
        "type": "inject",
        "z": "b4c0cd5a.eecca",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": true,
        "x": 110,
        "y": 80,
        "wires": [
            [
                "56d75330.2c8aac"
            ]
        ]
    },
    {
        "id": "7c15aa15.3ac984",
        "type": "json",
        "z": "b4c0cd5a.eecca",
        "name": "",
        "pretty": true,
        "x": 570,
        "y": 80,
        "wires": [
            [
                "4367b9e1.37ef68",
                "172a731f.65439d"
            ]
        ]
    },
    {
        "id": "172a731f.65439d",
        "type": "ui_template",
        "z": "b4c0cd5a.eecca",
        "group": "8a0760af.f3002",
        "name": "FTP Destinations",
        "order": 0,
        "width": 0,
        "height": 0,
        "format": "<md-input-container>\n    <label>Destination ID</label>\n    <input name=\"dest_id\" ng-model=\"msg.payload.dest_id\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required type=\"number\" step=\"any\" name=\"rate\" min=\"1\" max=\"50\">\n</md-input-container>\n<md-input-container>\n    <label>IP Address</label>\n    <input name=\"ip_adr\" ng-model=\"msg.payload.ip_adr\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n</md-input-container>\n<md-input-container>\n    <label>Username</label>\n    <input name=\"username\" ng-model=\"msg.payload.username\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n</md-input-container>\n<md-input-container>\n    <label>Password</label>\n    <input name=\"password\" ng-model=\"msg.payload.password\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required type=\"password\">\n</md-input-container>\n<md-input-container>\n    <label>Directory</label>\n    <input name=\"dir\" ng-model=\"msg.payload.dir\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n</md-input-container>\n<md-checkbox name=\"mandatory\" ng-model=\"msg.payload.mandatory\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n    Mandatory\n</md-checkbox>\n<md-checkbox name=\"compress\" ng-model=\"msg.payload.compress\" ng-change=\"msg1.payload = msg.payload;msg1.topic = msg.topic; send(msg1)\" required>\n    Compress\n</md-checkbox>",
        "storeOutMessages": true,
        "fwdInMessages": false,
        "templateScope": "local",
        "x": 790,
        "y": 120,
        "wires": [
            [
                "d05e321b.82a98",
                "b0a4d18d.39aa8"
            ]
        ]
    },
    {
        "id": "b0a4d18d.39aa8",
        "type": "debug",
        "z": "b4c0cd5a.eecca",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "false",
        "x": 1070,
        "y": 140,
        "wires": []
    },
    {
        "id": "e590899c.be8a18",
        "type": "ui_group",
        "z": "",
        "name": "App Settings",
        "tab": "bb87b365.247b1",
        "order": 1,
        "disp": true,
        "width": "6"
    },
    {
        "id": "8a0760af.f3002",
        "type": "ui_group",
        "z": "",
        "name": "FTP Destinations",
        "tab": "bb87b365.247b1",
        "order": 2,
        "disp": true,
        "width": "6"
    },
    {
        "id": "bb87b365.247b1",
        "type": "ui_tab",
        "z": "",
        "name": "Module Settings",
        "icon": "dashboard"
    }
]


 

Dave C-J

unread,
Jan 16, 2018, 3:40:07 AM1/16/18
to node...@googlegroups.com
Steve
Interesting idea - Would you like to take this to another thread to discuss/design/debate ?
Would be a great PR to have.

Julian Knight

unread,
Jan 16, 2018, 4:08:11 AM1/16/18
to Node-RED
I agree with Dave that this sounds like an interesting idea and a nice enhancement to Dashboard that might help simplify some types of interface processing.

With admittedly little thought, I would think that a form_button element would be the most consistent way to implement alternatively a checkbox on the group (though that may be a little too "magic" for starters to get to grips with quickly).

steve rickus

unread,
Jan 16, 2018, 9:39:04 AM1/16/18
to Node-RED
Sure... would it be more helpful to open the discussion as a new github issue? Or just use this mailing list?

Dave C-J

unread,
Jan 16, 2018, 1:00:42 PM1/16/18
to node...@googlegroups.com
Either is good
Reply all
Reply to author
Forward
0 new messages