You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -23,81 +23,128 @@ Provide custom JS and HTML (including any [Vuetify components](https://vuetifyjs
23
23
24
24
<PropsTable/>
25
25
26
-
## Built In Functionality
26
+
## Writing Custom Widgets
27
27
28
-
Any Vue Components that you define in `ui-template` extend the underlying `ui-template` Vue component. This includes a collection of builtin methods, data and supported Widgets. You can also render dynamic content using any VueJS data-binding expressions, (e.g. `v-if`, `v-for`).
28
+
UI Template will parse different tags and render them into Dashboard. The available tags are:
29
29
30
-
### Vuetify Widgets
30
+
-`<template>` - Any HTML code in here will be rendered into the Dashboard.
31
+
-`<script>` - Any JavaScript code in here will be executed when the widget is loaded. You can also [define a full VueJS component](#building-full-vue-components) here.
32
+
-`<style>` - Any CSS code in here will be injected into the Dashboard.
31
33
32
-
The `ui-template` node also has access to the [Vuetify component library](https://vuetifyjs.com/en/components/all/) by default. The library provides a large number of pre-built widgets that you can use in your Dashboard.
34
+
### Built-in Variables
33
35
34
-
These are particularly useful as they provide easy access to a large number of pre-built widgets that aren't necessarily included in the core nodes of Node-RED Dashboard 2.0.
36
+
You have access to a number of built-in variables in your `ui-template` node:
35
37
36
-
Some example widgets that you may find useful are:
38
+
-`this.id` - The ID of the `ui-template` node, assigned by Node-RED.
39
+
-`this.$socket` - The socket.io connection that is used to communicate with the Node-RED backend.
40
+
-`this.msg` - The last message received by the `ui-template` node.
37
41
38
-
-[File Input](https://vuetifyjs.com/en/components/file-inputs/) - Allows for the selection of a file from the user's local filesystem.
39
-
-[Star Rating Widget](https://vuetifyjs.com/en/components/ratings/) - A star rating widget, where users can select a rating from 1-n stars.
40
-
-[Progress Linear](https://vuetifyjs.com/en/components/progress-linear/) - A horizontal bar to show progress of a task or single bar-graph type visualisations.
42
+
### Built-in Functions
41
43
42
-
### Reading Node Input
44
+
We also offer some helper functions for the Node-RED integration too:
43
45
44
-
Whenever a `ui-template` receives a `msg` in Node-RED, that is automatically assigned to the `msg` variable in the template.
46
+
-`this.send` - Send a message to the Node-RED flow.
47
+
-`this.$socket.on('msg-input' + this.id, (msg) = { ... })` - will listen to any messages received by your `ui-template `node and react accordingly.
45
48
46
-
Additionally, we also bind a computed variable `value` to `msg.payload`. This means that you can access the `msg` object in your template, as well as binding the `value` variable to any widgets you use.
49
+
### Example (Raw JavaScript)
47
50
48
-
Such an example would be:
51
+
Putting this together, here is a simple starter widget that will alert the user when they click the button, and send a message into Node-RED.
{data-zoomable}
59
+
<script>
60
+
/* Write any JavaScript here */
61
+
// add our onClick function to the window object to make it accessible by the HTML <button>
62
+
window.onClick = function () {
63
+
alert('Button has been clicked')
64
+
}
58
65
59
-
### Sending Messages in Node-RED
66
+
// Use send() function to pass on data back into Node-RED:
67
+
this.send('Component has loaded')
60
68
61
-
Two exposed methods, `send` and `submit`, allow you to send messages from the Dashboard to the Node-RED flow.
-`send` - Outputs a message (defined by the input to this function call) from this node in the Node-RED flow.
64
-
-`submit` - Send a `FormData` object when attached to a `<form>` element. The created object will consnist of the `name` attributes for each form element, corresponding to their respective `value` attributes.
76
+
<style>
77
+
/* define any styles here - supports raw CSS */
78
+
.my-class {
79
+
color: red;
80
+
}
81
+
</style>
82
+
```
65
83
66
-
#### Sending on Click
67
-
Here, we call it when someone clicks our "Send Hello World" button:
It is possible to load external dependencies into your `ui-template` node. This is useful if you want to use a library that isn't included in the core Node-RED Dashboard 2.0 nodes.
87
+
88
+
To do this, you'll need to load the dependency in the `<script>` section of your template. For example, to load the [Babylon.js](https://www.babylonjs.com/) library, you would do the following:
Or another example, where the payload is automatically sent any time the `v-model` is changed:
94
+
You can then have _another_`<script />` tag in the same `ui-template` that utilises this library.
75
95
76
-
{data-zoomable}
96
+
An important caveat here is that, whilst this does get injected into the `<head />` of the Dashboard, because our widgets are loaded after the initial page load, the library isn't always available straight away as your Widget and HTML loads.
97
+
98
+
If you need access to the library as soon as it's available, the trick to this is to run a `setInterval()` and watch the `window` object for the library to be loaded.
`v-model` in Vue is a way of two-way binding a variable to a widget. Here, we bind the `value` variable to the `v-rating` widget. Then we watch for changes on that value with `@update:modelValue` and send the `value` variable to the Node-RED flow via `msg.payload`.
When changed, if wired to a "Debug" node, then we can see the resulting outcome is as follows:
109
+
<script>
110
+
function init () {
111
+
alert('Babylon.js is loaded')
112
+
}
86
113
87
-
{data-zoomable}
114
+
// run this code when the widget is built
115
+
let interval = setInterval(() => {
116
+
if (window.BABYLON) {
117
+
// call an init() to use BABYLON
118
+
init();
119
+
// Babylon.js is loaded, so we can now use it
120
+
clearInterval(interval);
121
+
}
122
+
}, 100);
123
+
</script>
124
+
```
88
125
89
126
## Building Full Vue Components
90
127
91
-
You can also build full Vue components in the `ui-template` node. This allows you to build your own bespoke behaviour, and gives you more control over the UI.
128
+
You can build full Vue components in the `ui-template` node, using VueJS's [Options API](https://vuejs.org/api/#options-api). This allows you to build your own bespoke behaviour, and gives you more control over the UI.
129
+
130
+
A full list of the VueJS Options API properties that we currently support are:
131
+
132
+
-`name` - The name of your component
133
+
-`data` - A function that returns data you want available across your component (in both `<template>` and `<script>` sections)
134
+
-`watch` - Run a function anytime a particular component variable changes
135
+
-`computed` - Calculate a variable based on other variables in your component
136
+
-`methods` - Define functions that can be called from your `<template>` or `<script>` sections
137
+
-`mounted` - Run code when the component is first loaded
138
+
-`unmounted` - Run code when the component is removed from the Dashboard
92
139
93
-
To do this in `ui-template` you need to define a `<template>` and `<script>` section in your template.
140
+
### Example (Full Vue Component)
94
141
95
-
For example, here we define a counter widget:
142
+
Here we define a counter widget, and utilise Vue's `data`, `watch`, `computed` and `methods` properties. This widget will automatically update the `formattedCount` variable whenever the `count` variable changes and will send a message to Node-RED whenever the `count` variable reaches a multiple of 5.
@@ -110,12 +157,13 @@ For example, here we define a counter widget:
110
157
// define variables available component-wide
111
158
// (in <template> and component functions)
112
159
return {
160
+
loaded: false,
113
161
count: 0
114
162
}
115
163
},
116
164
watch: {
117
165
// watch for any changes of "count"
118
-
count() {
166
+
count: function () {
119
167
if (this.count % 5 === 0) {
120
168
this.send({payload: 'Multiple of 5'})
121
169
}
@@ -124,15 +172,23 @@ For example, here we define a counter widget:
124
172
computed: {
125
173
// automatically compute this variable
126
174
// whenever VueJS deems appropriate
127
-
formattedCount() {
175
+
formattedCount: function () {
128
176
return `${this.count} Apples`
129
177
}
130
178
},
131
179
methods: {
132
180
// expose a method to our <template> and Vue Application
133
-
increase() {
181
+
increase: function () {
134
182
this.count++
135
183
}
184
+
},
185
+
mounted() {
186
+
// code here when the component is first loaded
187
+
this.loaded = true
188
+
},
189
+
unmounted() {
190
+
// code here when the component is removed from the Dashboard
191
+
// i.e. when the user navigates away from the page
136
192
}
137
193
}
138
194
</script>
@@ -150,99 +206,67 @@ We can also `watch` any of these `data` variables, and react accordingly. For ex
150
206
151
207
We use a `computed` variable which will automatically update whenever the `count` variable changes. This allows us to format the `count` variable in a way that is more useful to us to display, without affecting the underlying `count` variable.
152
208
153
-
### Running code on load
209
+
##Additional Examples
154
210
155
-
In VueJS, you can run code when a component is loaded by using the `mounted()` function. This is called when the component is first loaded into the Dashboard:
211
+
Any Vue Components that you define in `ui-template` extend the underlying `ui-template` Vue component. This includes a collection of builtin methods, data and supported Widgets. You can also render dynamic content using any VueJS data-binding expressions, (e.g. `v-if`, `v-for`).
156
212
157
-
```vue
213
+
### Reading Node-RED Input
214
+
215
+
Whenever a `ui-template` receives a `msg` in Node-RED, that is automatically assigned to the `msg` variable in the template. Such an example would be:
216
+
217
+
```html
158
218
<template>
159
-
<div style="display: flex; gap: 8px;">
160
-
<label>Has Loaded:</label>
161
-
<code>{{ loaded }}</code>
219
+
<div>
220
+
<h2>Latest <code>msg</code> received:</h2>
221
+
<pre>{{ msg }}</pre>
162
222
</div>
163
223
</template>
164
-
165
-
<script>
166
-
export default {
167
-
data() {
168
-
return {
169
-
loaded: false
170
-
}
171
-
},
172
-
mounted() {
173
-
this.loaded = true
174
-
}
175
-
}
176
-
</script>
177
224
```
178
225
179
-
If you want to do the inverse, run code when your widget is removed from the screen, you can use the `unmounted()` function.
226
+
{data-zoomable}
180
227
181
-
### VueJS Options API
228
+
### Sending Messages to Node-RED
182
229
183
-
We are utilising VueJS's [Options API](https://vuejs.org/api/#options-api) here as it's far easier to merge with the `ui-template` component. Unfortunately, at the moment, we do not support the [Composition API](https://vuejs.org/api/#composition-api).
230
+
Two exposed methods, `send` and `submit`, allow you to send messages from the Dashboard to the Node-RED flow.
184
231
185
-
A full list of the VueJS Options API properties that we currently support are:
232
+
-`send` - Outputs a message (defined by the input to this function call) from this node in the Node-RED flow.
233
+
-`submit` - Send a `FormData` object when attached to a `<form>` element. The created object will consnist of the `name` attributes for each form element, corresponding to their respective `value` attributes.
186
234
187
-
-`name`
188
-
-`data`
189
-
-`watch`
190
-
-`computed`
191
-
-`methods`
192
-
-`mounted`
193
-
-`unmounted`
235
+
#### Sending on Click
236
+
Here, we call it when someone clicks our "Send Hello World" button:
It is possible to load external dependencies into your `ui-template` node. This is useful if you want to use a library that isn't included in the core Node-RED Dashboard 2.0 nodes.
242
+
#### Sending on Change
243
+
Or another example, where the payload is automatically sent any time the `v-model` is changed:
198
244
199
-
To do this, you'll need to load the dependency in the `<script>` section of your template. For example, to load the [Babylon.js](https://www.babylonjs.com/) library, you would do the following:
245
+
{data-zoomable}
You can then have _another_`<script />` tag in the same `ui-template`that utilises this library.
252
+
`v-model` in Vue is a way of two-way binding a variable to a widget. Here, we bind the `value` variable to the `v-rating` widget. Then we watch for changes on that value with `@update:modelValue` and send the `value` variable to the Node-RED flow via `msg.payload`.
206
253
207
-
An important caveat here is that, whilst this does get injected into the `<head />` of the Dashboard, because our widgets are loaded after the initial page load, the library isn't always available straight away as your Vue component and HTML loads.
254
+
When changed, if wired to a "Debug" node, then we can see the resulting outcome is as follows:
208
255
209
-
If you need access to the library as soon as it's available, the trick to this is to run a `setInterval()` and watch the `window` object for the library to be loaded.
256
+
{data-zoomable}
// call an init() function defined in this component
228
-
this.init();
229
-
}
230
-
}, 100);
231
-
},
232
-
methods: {
233
-
init () {
234
-
// do stuff with BABYLON here
235
-
}
236
-
}
237
-
}
238
-
</script>
239
-
```
260
+
The `ui-template` node also has access to the [Vuetify component library](https://vuetifyjs.com/en/components/all/) by default. The library provides a large number of pre-built widgets that you can use in your Dashboard.
240
261
241
-
## Writing Raw JavaScript
262
+
These are particularly useful as they provide easy access to a large number of pre-built widgets that aren't necessarily included in the core nodes of Node-RED Dashboard 2.0.
242
263
243
-
You are not limited to having to use a Vue components, as you can also write raw JavaScript in the `ui-template` node. This code will then run as the widget is loaded into Dashboard.
264
+
Some example widgets that you may find useful are:
244
265
266
+
-[File Input](https://vuetifyjs.com/en/components/file-inputs/) - Allows for the selection of a file from the user's local filesystem.
267
+
-[Star Rating Widget](https://vuetifyjs.com/en/components/ratings/) - A star rating widget, where users can select a rating from 1-n stars.
268
+
-[Progress Linear](https://vuetifyjs.com/en/components/progress-linear/) - A horizontal bar to show progress of a task or single bar-graph type visualisations.
245
269
246
-
##Examples
270
+
### Articles & Tutorials
247
271
248
272
-[Building a Custom Video Player with UI Template](https://flowfuse.com/blog/2023/12/dashboard-0-10-0/)
0 commit comments