UNPKG

node-red-contrib-uibuilder

Version:

Easily create data-driven web UI's for Node-RED. Single- & Multi-page. Multiple UI's. Work with existing web development workflows or mix and match with no-code/low-code features.

442 lines (305 loc) 22 kB
--- title: Working with the uibuilderfe Front-End Library description: | How to work with UIBUILDER's front-end library in your own UI code. created: 2021-02-17 14:28:00 lastUpdated: 2023-09-30 17:16:17 updated: 2024-03-22 17:53:26 --- > [!WARNING] > This page refers to the "old" original front-end library for UIBUILDER. There is now a new library that will eventually replace this one. Please see [the new front-end library pages](client-docs/readme.md). This older library has been functionally stabilised (there will not be any further enhancements after UIBUILDER v5). It still works as of UIBUILDER v6.0 but will eventually be deprecated. `uibuildefe.js` is the library that lets you interact with your `uibuilder` nodes in Node-RED. It manages the communications and provides a number of helper functions to make life easy. The detailed documentation for the library is in the [uibuildefe developer documentation](uibuilderfe-js). If you don't find what you need here, please look there. ## Contents - [Contents](#contents) - [Startup](#startup) - [Startup Optional Parameters](#startup-optional-parameters) - [Parameters](#parameters) - [Examples](#examples) - [Errors](#errors) - [Events](#events) - [Example onChange event handler](#example-onchange-event-handler) - [Currently available pre-defined events](#currently-available-pre-defined-events) - [Variable Handling](#variable-handling) - [Helper Methods (functions)](#helper-methods-functions) - [`autoSendReady` Turn on/off the ready for content control msg](#autosendready-turn-onoff-the-ready-for-content-control-msg) - [`clearEventListeners` Forcibly removes all event listeners from the events array](#cleareventlisteners-forcibly-removes-all-event-listeners-from-the-events-array) - [`debug` Turn on/off debugging console messages](#debug-turn-onoff-debugging-console-messages) - [`eventSend` Helper fn to send event data](#eventsend-helper-fn-to-send-event-data) - [`get` Get the value of a uibuilder variable](#get-get-the-value-of-a-uibuilder-variable) - [`me` Return uibuilder info](#me-return-uibuilder-info) - [`msg` Convenience method to access the last standard msg from Node-RED](#msg-convenience-method-to-access-the-last-standard-msg-from-node-red) - [`onChange` Subscribe to a uibuilder variable change event](#onchange-subscribe-to-a-uibuilder-variable-change-event) - [`send` Send a standard msg to Node-RED](#send-send-a-standard-msg-to-node-red) - [`sendCtrl` Send a control msg to Node-RED](#sendctrl-send-a-control-msg-to-node-red) - [`set` Set the value of a uibuilder variable, creates subscribable event for changes](#set-set-the-value-of-a-uibuilder-variable-creates-subscribable-event-for-changes) - [`setOriginator` Sets an originating node ID](#setoriginator-sets-an-originating-node-id) - [`setPing` Check if Node-RED/uibuilder server is alive, may be used to trigger session extensions](#setping-check-if-node-reduibuilder-server-is-alive-may-be-used-to-trigger-session-extensions) - [`showComponentDetails` (VueJS only) Return a control msg contining details of a Vue component](#showcomponentdetails-vuejs-only-return-a-control-msg-contining-details-of-a-vue-component) - [`showToast` Shows a popup message in the UI](#showtoast-shows-a-popup-message-in-the-ui) - [`start` Start up the front-end library](#start-start-up-the-front-end-library) - [`uiDebug` Conditional debug output (controlled by debug setting)](#uidebug-conditional-debug-output-controlled-by-debug-setting) ## Startup In order to use the front-end library for uibuilder, you must call the start function: `uibuilder.start()`. This should be called once all of the page resources have loaded & the core DOM has rendered. ### Startup Optional Parameters If initialising this library from a page that is _not in the root folder_ for the uibuilder instance (or indeed is from a different server), the library cannot work out the correct Socket.io path nor the actual root URL and so you have to supply this yourself. e.g. In addition, if you are using VueJS, you can pass the Vue app instance to the `start` function to allow uibuilder to work some magic such as providing direct access to the toast popups code-free. #### Parameters * `namespace` {Object=|string=} Optional. One of: * Object containing ref to vueApp, * Object containing settings using the property names given here, or * IO Namespace override. Changes self.ioNamespace from the default. If you are not sure about the correct namespace, use the "Instance Details" button in the `uibuilder` node configuration panel (in the Node-RED Editor) and search for "ioNamespace" in the resulting page. The namespace to use here is that result prefixed with a leading `/`. However if you are serving your code from a different server or a different port on the same server (e.g. when using a build tool dev server), you must include the full URL of Node-RED (or the uibuilder custom URL if using its custom ExpressJS server feature). * `ioPath` {string=} Optional. **Note that you should not need to change this**. It changes self.ioPath from the default The ioPath is a combination of: * A leading `/`, * `httpNodeRoot` - normally empty unless you have changed it in `settings.js` * "/uibuilder/vendor/socket.io" While uibuilderfe does its best to work out the ioPath (from cookies first and then the request url), it cannot always determine the httpNodeRoot. Sometimes, if you are serving your js code from a different server or a different url path on the same server (e.g. when using a build tool dev server), it may not be possible. It is in these cases that you must specify it manually. From v5, this should now rarely be needed. * `vueApp` {Object=} Optional. reference to the VueJS instance ### Examples ```javascript // Socket.io Namespace, IO path (no httpNodeRoot defined) uibuilder.start('/uiburl', '/uibuilder/vendor/socket.io') ``` ```javascript // Just passes the VueJS app object to enable Vue magic functions uibuilder.start(this) ``` ```javascript // Pass a settings object uibuilder.start({ namespace: '/uib', ioPath: '/nr/uibuilder/vendor/socket.io', // httpNodeRoot defined as "nr" in settings.js vueApp: this }) ``` ### Errors If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages in your browser console, the most likely reason is that you need to pass the namespace and path parameters because the library can't work them out. But first, check the content of the uibuilder cookies using your browser's dev-tools to make sure that they contain something sensible. If you get sudden client disconnects. Check the size of the data you are sending or recieving. When Socket.IO changed from v2 to v3, they changed the default maximum msg size from 100MB to 1MB. If you try to send a msg in either direction that is >1MB, the socket will disconnect. You can change this size by changing the `uibuilder.socketOptions` in `settings.json`. ```javascript /** Optional: Socket.IO Server options * See https://socket.io/docs/v4/server-options/ * Note that the `path` property will be ignored, it is set by uibuilder itself. * You can set anything else though you might break uibuilder unless you know what you are doing. * @type {Object} */ socketOptions: { // Make the default buffer larger (default=1MB) maxHttpBufferSize: 1e8 // 100 MB }, ``` ## Events uibuilderfe has its own, simple, event handling system. This lets you "subscribe" to an event with a function that is exectuted automatically when the event fires. Events are created automatically by the internal `self.set` function that is used to update variables. So any internal variable updated this way automatically gets an event named after the variable name. In addition, using `uibuilder.set('varname', newVal)` also creates an event. Events are subscribed to using the `uibuilder.onChange(evtName, callback)` function. Where the callback is a function that is executed whenever anything triggers that event name. Event processing is highly efficient since nothing actually happens if no `onChange` function has been registered against an event. Multiple `onChange` callbacks can be assigned to an event which is helpful if you have front-end code such as components. In general though, try to minimise the number of `onChange` entries. Most commonly, the only `onChange` event handler you will define is the one that fires whenever a msg is received from Node-RED: ### Example onChange event handler The most common event used is when the `msg` variable is updated by an incoming message from Node-RED. ```javascript uibuilder.onChange('msg', function(msg){ console.info('msg received from Node-RED server:', msg) }) ``` ### Currently available pre-defined events * `ctrlMsg` - triggered whenever the client receives a control message from the server. * `ioConnected` - triggered whenever the client connects or disconnects from the server over Socket.IO. <!-- * `isAuthorised` - triggered by successful logon or logoff (on receipt of confirmation from server). --> * `msg` - triggered whenever the client receives a standard msg from the server. e.g. you send a msg into the input port of the node. * `msgsCtrl` - triggered whenever the client receives a control message from the server. NOTE: This is superfluous and may be removed in a future release. * `msgsReceived` - triggered whenever the client receives a standard msg from the server. Counts the number of messages received. NOTE: This is superfluous and may be removed in a future release. * `msgsSent` - triggered whenever the client sends a standard message to the server. NOTE: This is superfluous and may be removed in a future release. * `msgsSentCtrl` - triggered whenever the client sends a control message to the server. NOTE: This is superfluous and may be removed in a future release. * `ping` - triggered as a result(s) of a `uibuilder.setPing(ms)`. Contains the resulting status and returned headers. * `sentCtrlMsg` - triggered whenever the client sends a control message to the server. * `sentMsg` - triggered whenever the client sends a standard message to the server. * `serverShutdown` - triggered when the Node-RED server sends a shutdown control msg to the client. This happens before Node-RED actually shuts down. No data is returned to the callback in this case. * `serverTimeOffset` - triggered when the Node-RED server sends the initial connection message to the client. * `socketError` - triggered if the server sends a socket error to the client. Probably triggered by socket middleware. Returns the error as data to the callback. ## Variable Handling All public variables must be accessed from your own code using the getter: ```javascript var myvar = uibuilder.get('varName') ``` All public variables must be changed from your own code using the setter: ```javascript uibuilder.set('varName',value) ``` You can use the setter to add your own variables to the `uibuilder` object. These will then have an event handler attached so that you can monitor for changes with `uibuilder.onChange('varName', function(varName) { ... })` The list of accessible, pre-defined variables is provided on the [uibuildefe-js developer documentation page](uibuilderfe-js?id=public-variables). ## Helper Methods (functions) uibuilderfe has a number of helper functions that are aimed at making life easier for the author of a web UI. <!-- ### `autoMap` --> ### `autoSendReady` Turn on/off the ready for content control msg Turns on/off the "ready for content" control message that is normally sent back to Node-RED on window.load Set to false early in the processing if you want to get control over when Node-RED sends you data. ### `clearEventListeners` Forcibly removes all event listeners from the events array Use if you need to re-initialise the environment. ### `debug` Turn on/off debugging console messages Turns on/off debugging. See the output in your browser's developer console. Example: `uibuilder.debug(true)` Best used in the `created` section of Vue or similar frameworks. ### `eventSend` Helper fn to send event data A simple helper function designed to be the target method for DOM events. Typically used for the click event handler for a button. A msg will be sent back to Node-RED containing some information as shown in the example below _Vue/bootstrap-vue example_: In `index.html` ```html <b-button id="myButton1" @click="doEvent" data-something="hello"></b-button> ``` Note that all `data-xxxx` attributes are In `index.js` ```javascript // ... methods: { doEvent: uibuilder.eventSend, }, // ... ``` The msg returned to Node-RED will be: ```json { "topic": "", // Optional. Will include the topic from the last inbound msg if it is available "uibDomEvent": { // The html id attribute. If that doesn't exist, the name attribute // is used. If that doesn't exist, the 1st 25 chars of the inner text is used "sourceId": "myButton1", // The DOM event that triggered the function "event": "click", }, // Each `data-xxxx` attribute is added as a property // - this may be an empty Object if no data attributes defined "payload": { "something": "hello" } } ``` ### `get` Get the value of a uibuilder variable Get the value of a variable inside the library. Note that the get function protects private variables preventing easy access. This is not a security function since JavaScript has no mechanism for completely protecting private variables. <!-- ### `logon` Send a logon (authentication) control request to Node-RED Sends a specially formatted control msg back to Node-RED (output port 2 of the node). This is processed internally by uibuilder. A response control msg is sent back that determines whether the logon request was successful. If it was, the `isAuthorised` variable is changed to either true or false. Example of handling the `isAuthorised` change with VueJS (this goes in the `mounted` section): ```javascript // If user is logged on/off uibuilder.onChange('isAuthorised', function(isAuthorised){ console.info('[indexjs:uibuilder.onChange:isAuthorised] isAuthorised changed. User logged on?:', isAuthorised) console.log('authData: ', uibuilder.get('authData')) vueApp.isLoggedOn = isAuthorised }) ``` The function **must** be passed the correct data structure. See the [security documentation for details](security). The authentication data is retained internally to `uibuilderfe` in the `authData` object. ### `logoff` Send a logoff control request to Node-RED Sends a specially formatted control msg back to Node-RED (output port 2 of the node). This is processed internally by uibuilder. A response msg is sent back that determines whether the logoff request was successful. If it was, the `isAuthorised` variable is changed to either true or false. Once uibuilderfe recieves confirmation that the logoff was successful, it automatically clears the internal `authData` data object. --> ### `me` Return uibuilder info Returns the front-end library version as a string unless debugging is turned on. In which case it returns the full `self` object - use with caution. ### `msg` Convenience method to access the last standard msg from Node-RED A convenience method, returns the current value of the last received standard (not control) message. ### `onChange` Subscribe to a uibuilder variable change event Subscribe to an event. Has two parameters. The first is the name of the event, the second is a callback function to be triggered when the event is fired. Example: ```javascript uibuilder.onChange('msg', function(msg){ console.info('msg received from Node-RED server:', msg) }) ``` ### `send` Send a standard msg to Node-RED Send a standard message back to Node-RED. Requires an object as its single parameter. The object is the msg object to be sent. The library will add some standard properties to the message so you only need to add your own data. ### `sendCtrl` Send a control msg to Node-RED Send a control message back to Node-RED. Requires an object as its single parameter. The object is the msg object to be sent. Note that you shouldn't really need to ever send a control msg since the library takes care of all of that. However, there may be rare occasions when you might want to do something like trigger a cache replay or cache clear. The library will add some standard properties to the message so you only need to add your own data. ### `set` Set the value of a uibuilder variable, creates subscribable event for changes Set a variables value inside the library. Also creates an event that can be subscribed to using the `onChange` function. Note that the set function protects private variables and prevents the overwriting of internal function names. ### `setOriginator` Sets an originating node ID Manually sets the default originator node id. Not generally required since the uib-sender node will set the originator automatically in the message it sends and this will be used by the fe. However, might be useful if you want to return a msg to a specific node. However, the node would need to be a custom node that recognises it otherwise, you would need to route the msg yourself in your flow. ### `setPing` Check if Node-RED/uibuilder server is alive, may be used to trigger session extensions Calling without an argument or with it set to `0` (zero), will cancel any repeating pings and will send an individual ping to the uibuilder ping URL. With a non-zero argument, will repeatedly ping every n milliseconds. You can use this to check whether the uibuilder web server is alive. It could also be used to automatically extend a client security session (via an external proxy or via the ExpressJS uibuilder custom middleware function). It also returns some data including the HTTP status number and the server response headers. So it can be a useful way to obtain the ExpressJS server response headers. ### `showComponentDetails` (VueJS only) Return a control msg contining details of a Vue component This sends a control msg back to Node-RED containing details of a specified VueJS Component. See the [Working with Vue Components](vue-component-handling) documentation page for details. Note that to use this, you **must** have an instance of the component in your HTML and that **must** have a `ref` attributed on it. Note that you can trigger this automatically (without front-end code) by sending a msg from Node-RED in the form: ``` { "_uib": { "requestDetails": true, "componentRef": "tabOne", "options": {} } } ``` The returned control message to Node-RED looks like: ``` { "uibuilderCtrl":"vue component details", "componentDetails": { "ref":"tabOne", "tag":"b-tab", "props": [ "id","active","buttonId","disabled","lazy", "noBody","tag","title","titleItemClass", "titleLinkAttributes","titleLinkClass" ] }, "topic":"uibuilder", "from":"client", "_socketId":"/extras#mw2GKTo7sLTn9Q-AAAAH", "_msgid":"ed7d78ba.ecfe88" } ``` ### `showToast` Shows a popup message in the UI Creates a popup message (a "Toast") that overlays your web UI. See the [Working with Vue Components](vue-component-handling) documentation page for details. Note that you can trigger this automatically (without front-end code) by sending a msg from Node-RED in the form: ```jsonc { "_uib": { // This can actually be anything, if it doesn't exist, // the toast will appear in the default location "componentRef": "globalNotification", // Note that most if not all of these are optional, // they correspond to bootstrap-vue's b-toast props "options": { "title": "This is the <i>title</i>", "content": "This is content <span style=\"color:red;\">in addition to</span> the payload", "append": true, "autoHideDelay": 1500, "variant": "info", "solid": true, "href": "https://bbc.co.uk", "toaster": "b-toaster-top-center", "noAutoHide": true } } } ``` You can also trigger it from within your front-end code with: ```js /** Show a pop-over msg * @argument {string} Text to show * @argument {string|null} Location to show the toast (Vue/Bootstrap-vue only) * @argument {object|null} Options that control the toast display */ uibuilder.showToast("Hello",null,{"variant": "warn"}) ``` ### `start` Start up the front-end library Start the uibuilderfe library. See the [Startup section](#startup) for details. This is not automatic because if it were, it would not be possible to use this library with web pages that are not in the root URL folder. For example, if you have a uibuilder instance with a URL set to `myui`, your source code folder is probably in `~/.node-red/uibuilder/myui/src`. HTML files in that folder will be able to start uibuilderfe with a simple `uibuilder.start()`. But if you create a sub-folder, say `utils`, any HTML file there will pick up the wrong settings for the websocket connection and will need the override parameters in the start function. Similarly, it is even possible to serve a uibuilderfe page from a different web server alltogether. In this case you would also need to specify the websocket connection parameters. ### `uiDebug` Conditional debug output (controlled by debug setting) A convenience method for conditionally outputting debug messages to the browser console. Two arguments, the first being the `type` which is one of log, error, info, or dir The second being the data to show. If uibuilder.debug is set to false, nothing will be output.