Skip to content

Commit

Permalink
Merge pull request #1475 from bartbutenaers/template-dynamic
Browse files Browse the repository at this point in the history
Dynamic ui-template
  • Loading branch information
joepavitt authored Dec 6, 2024
2 parents af1d14f + 23e339c commit fd37c72
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 191 deletions.
9 changes: 9 additions & 0 deletions docs/nodes/widgets/ui-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ props:
Scope: "Template nodes can be used for 3 purposes/scopes: <ul><li><b>Widget (Group-Scoped):</b>A standard HTML/Vue widget rendered in a group in the Dashboard.</li><li><b>Widget (Page-Scoped):</b>A HTML/Vue widget that will render on a page, outside of any existing groups. Note that these widgets will render after any Groups. An example use case for this would be if you wanted to have a fixed footer on a given page.</li><li><b>Widget (UI-Scoped):</b>A HTML/Vue widget rendered on every page of the Dashboard. Most commonly used in conjunction with <a href=\"#teleports\">Teleports</a></li><li><b>CSS (All Pages):</b>Define custom CSS classes/styling that applies to the entire Dashboard.</li><li><b>CSS (Single Page):</b>Define custom CSS classes/styling that applies just a single page of your Dashboard.</li></ul>"
Class: Appends CSS classes to the widget
Template: The content of the widget or CSS &lt;style&gt;. If using this for CSS, you do not need to include any &lt;style&gt; tags, as these will be automatically added.
dynamic:
Format:
payload: msg.ui_update.format
structure: ["String"]
---

<script setup>
Expand All @@ -30,6 +34,10 @@ Provide custom JS and HTML (including any [Vuetify components](https://vuetifyjs

<PropsTable/>

## Dynamic Properties

<DynamicPropsTable/>

## Writing Custom Widgets

UI Template will parse different tags and render them into Dashboard. The available tags are:
Expand Down Expand Up @@ -476,3 +484,4 @@ Some example widgets that you may find useful are:
### Articles & Tutorials

- [Building a Custom Video Player with UI Template](https://flowfuse.com/blog/2023/12/dashboard-0-10-0/)

3 changes: 1 addition & 2 deletions nodes/widgets/locales/en-US/ui_template.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

<script type="text/markdown" data-help-name="ui-template">
(see [full docs](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html))

Expand Down Expand Up @@ -150,4 +149,4 @@
}
```

</script>
</script>
43 changes: 30 additions & 13 deletions nodes/widgets/ui_template.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
const statestore = require('../store/state.js')

module.exports = function (RED) {
function TemplateNode (config) {
const node = this

// create node in Node-RED
RED.nodes.createNode(this, config)

const evts = {
onAction: true // TODO: think we need an onSend event for template nodes that matches up with a `widget-send` message
}

if (config.templateScope === 'local') {
config.page = ''
config.ui = ''
Expand All @@ -31,18 +29,37 @@ module.exports = function (RED) {
config.passthru = true
}

// which group are we rendering this widget
// determine which group/page/ui are we rendering this widget
let group, page, ui
if (config.group) {
const group = RED.nodes.getNode(config.group)
// inform the dashboard UI that we are adding this node
group.register(node, config, evts)
group = RED.nodes.getNode(config.group)
} else if (config.page) {
const page = RED.nodes.getNode(config.page)
// inform the dashboard UI that we are adding this node
page.register(null, node, config, evts)
page = RED.nodes.getNode(config.page)
} else if (config.ui) {
const ui = RED.nodes.getNode(config.ui)
// inform the dashboard UI that we are adding this node
ui = RED.nodes.getNode(config.ui)
}

const evts = {
onAction: true, // TODO: think we need an onSend event for template nodes that matches up with a `widget-send` message
beforeSend: function (msg) {
if (msg.ui_update) {
const update = msg.ui_update
if (typeof update.format !== 'undefined') {
// dynamically set "format" property
const parent = group || page || ui
statestore.set(parent.getBase(), node, msg, 'format', update.format)
}
}
return msg
}
}

// inform the dashboard group/page/ui that we are adding this node
if (group) {
group.register(node, config, evts)
} else if (page) {
page.register(null, node, config, evts)
} else if (ui) {
ui.register(null, null, node, config, evts)
}
}
Expand Down
Loading

0 comments on commit fd37c72

Please sign in to comment.