Files
EVOLV/manuals/node-red/flowfuse-ui-template-manual.md
znetsixe 6a6c04d34b Migrate to new Gitea instance (gitea.wbd-rd.nl)
- Update all submodule URLs from gitea.centraal.wbd-rd.nl to gitea.wbd-rd.nl
- Add settler as proper submodule in .gitmodules
- Add agent skills, function anchors, decisions, and improvements
- Add Docker configuration and scripts
- Add manuals and third_party docs
- Update .gitignore with secrets and build artifacts
- Remove stale .tgz build artifact

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:07:04 +01:00

3.1 KiB

FlowFuse ui-template Manual (EVOLV Reference)

Source: https://dashboard.flowfuse.com/nodes/widgets/ui-template.html

Purpose

Custom Vue 3 / Vuetify / HTML widget. Full scripting, scoped CSS, send/receive messages.

Scopes

Scope Renders Use Case
Widget (Group) Inside a ui-group Custom gauges, tables, controls
Widget (Page) On page, outside groups Floating overlays, full-width banners
Widget (UI) On every page Global headers, footers
CSS (All Pages) N/A — injects <style> Global CSS overrides
CSS (Single Page) N/A — injects <style> Page-specific CSS

Properties

Property Type Dynamic Notes
group ref No Parent ui-group (Group scope)
page ref No Parent ui-page (Page scope)
width int No Columns
height int No Row units
format string Yes Vue template string
storeOutMessages bool No Persist last output for late joiners
passthru bool No Forward input to output
templateScope string No "widget:group", "widget:page", "widget:ui", "page:style", "site:style"

Template Structure

<template>
  <v-btn @click="send({payload: 'clicked'})">Click</v-btn>
  <p>Value: {{ msg.payload }}</p>
</template>
<script>
export default {
  data() { return { local: 0 }; },
  watch: {
    msg(val) { this.local = val.payload; }
  },
  methods: {
    doSend() { this.send({payload: this.local}); }
  },
  mounted() { /* one-time setup */ },
  unmounted() { /* cleanup */ }
};
</script>
<style scoped>
p { color: #2196f3; }
</style>

Built-in Variables

Variable Description
id This node's unique ID
msg Latest received message (reactive)
$socket Socket.io client for custom events

Sending Messages

this.send({ payload: 42, topic: "my-topic" });
this.submit();  // sends FormData from <form>

Receiving Messages

Option A — Vue watch:

watch: { msg(newMsg) { /* react */ } }

Option B — Socket listener:

mounted() {
  this.$socket.on('msg-input:' + this.id, (msg) => { /* handle */ });
}

Teleports (inject into dashboard chrome)

<Teleport to="#app-bar-actions">
  <v-btn>Custom Button</v-btn>
</Teleport>

Targets: #app-bar-title, #app-bar-actions.

Vuetify Components

All Vuetify 3 components are available without import: <v-btn>, <v-card>, <v-slider>, <v-data-table>, etc.

Dynamic Properties (msg.ui_update)

msg.ui_update = { format: "<p>New template content</p>" };

EVOLV Key Rules

  1. Use templates sparingly — prefer built-in widgets when they fit.
  2. For complex custom visualizations (SVG P&ID, animated schematics), template is the right choice.
  3. Always use <style scoped> to avoid leaking CSS to other widgets.
  4. Prefer watch: { msg } over socket listeners for simpler code.
  5. Keep templates under 100 lines — split complex UIs into multiple template nodes.