Currently, Node-RED Dashboard do not allow installing user created widget nodes. Instead, it supports TEMPLATE node which allows embedding HTML code in its setting panel. However, making new widget node installable is desirable because it enriches Node-RED Dashboard ecosystem as of current Node-RED nodes.
- Basic node code (HTML and JavaScript) structure follows those of template node (but can be arbitrary),
- Support code generation from existing TEMPLATE node using nodegen tool (optional).
-
Widget node is basically same as ordinary Node-RED node. Different point is that it requires accessing
ui.jsmodule of Node-RED Dashboard for accessing UI interfaces (e.g.ui.add). Becauseus.jsis stored undernode-red-dashboardmodule, we need some means for accessing it.Proposal:
-
Add interface (e.g.
getDashboardPath) for getting module install path ofnode-red-dashboard.- Can access other data stored under
node-red-dashboardsuch as icons. - As pointed on the last teleconference, this interface is too specialized for Node-RED Dashboard.
- Can access other data stored under
-
Add interface (e.g. getModulePath) for getting module installation path (or other information if there are good usage) of any module.
- This proposal is generarization of #1.
-
Add interface for accessing
ui.jsinterface from node API (i.e.REDvariable) passed on node initialization.- Similar to #1, this proposal is too specialized for Node-RED Dashboard.
-
other better way for accessing
ui.js?
Currently, we prefer #2 because this one is more general compared to other proposal.
-
-
Accessing interfaces of
us.jsmust be delayed afternode-red-dashboardis loaded.Proposal:
- Delay
requireofui.jsuntil widget node deployment.
- Delay
- HTML code
- Same as normal node described at (https://nodered.org/docs/creating-nodes/node-html).
- JavaScript code
- load
us.jsmodule using method of proposal#2, - call
us.addfunction with parameters similar to TEMPLATE node.
- load
-
HTML code
<script type="text/x-red" data-template-name="ui_hello"> ... help text ... </script> <script type="text/javascript"> function mk_conf(NAME) { ... create node definition ... }; RED.nodes.registerType('ui_hello', mk_conf('hello')); </script>
-
JavaScript code
module.exports = function(RED) { var TEMPLATE_SCOPE = "local"; // HTML code for widget var TEMPLATE = '// name: hello\n<div style=\"background-color:#84180F; color:#FFFFFF; border-radius:15px; font-size:20px;\" align=\"center\">\n Hello Node-RED\n</div>\n'; var STORE_OUT_MSGS = true; var FWD_IN_MSGS = true; var ui = undefined; function TemplateNode(config) { if(ui === undefined) { // load ui.js module var base = RED.nodes.getModulePath("node-red-dashboard"); ui = require(base+'/ui')(RED); } RED.nodes.createNode(this, config); var node = this; var group = RED.nodes.getNode(config.group); if (!group && TEMPLATE_SCOPE !== 'global') { return; } var tab = null; if (TEMPLATE_SCOPE !== 'global') { tab = RED.nodes.getNode(group.config.tab); if (!tab) { return; } if (!config.width) { config.width = group.config.width; } } var hei = Number(config.height || 0); // initialize UI widget var done = ui.add({ forwardInputMessages: FWD_IN_MSGS, storeFrontEndInputAsState: STORE_OUT_MSGS, emitOnlyNewValues: false, node: node, tab: tab, group: group, control: { type: 'template', order: config.order, width: config.width || 6, height: hei, format: TEMPLATE, templateScope: TEMPLATE_SCOPE }, ... }); node.on("close", done); } RED.nodes.registerType('ui_hello', TemplateNode); };
