Sliders, color pickers, dropdowns, etc., in Dashboard 2.0 Templates

Sorry if I missed this in the docs (or other posts here)

Can someone explain to me how I might include sliders, color pickers, and dropdowns in my Dashboard 2.0 Template node?

Do I need additional libraries, if so where / how can I install them? Will they be included by default in future releases? And how do I actually include them in the Template node, in terms of syntax?

Thanks

Mat

No. As described in the dashboard docs, you can use the verify components out of the box.

Provide custom JS and HTML (including any Vuetify components) to render in the Dashboard


The examples on the vuetify pages all have example code (the code button above each live demo) and they have a playground where you can test stuff.

Sliders I did once

Dropdown examples -

[{"id":"2086b1f86b7ea9cc","type":"group","z":"be4568a984cb4685","name":"Dropdowns","style":{"label":true,"color":"#000000","fill":"#e3f3d3"},"nodes":["686288d9473a0ad7","85ddcad5226e744c","58866c432c8047e0","6a5445d93e54827e","9161cc515f695ecd","f69abba39561daef"],"x":454,"y":79,"w":352,"h":162},{"id":"686288d9473a0ad7","type":"ui-template","z":"be4568a984cb4685","g":"2086b1f86b7ea9cc","group":"48fc19d1161f11e6","page":"","ui":"","name":"Menu","order":8,"width":"3","height":"1","head":"","format":"<template>\n  <div class=\"d-flex justify-space-around\">\n    <v-menu>\n      <template v-slot:activator=\"{ props }\">\n        <v-btn block color=\"primary\" v-bind=\"props\">\n          Select Option 1\n        </v-btn>\n      </template>\n      <v-list>\n        <v-list-item v-for=\"(item, index) in items\"\n            :key=\"index\"\n            :value=\"index\"\n            @click=\"send({payload: item.title})\">\n          <v-list-item-title>{{ item.title }}</v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n  </div>\n</template>\n\n<script>\n  export default {\n    data: () => ({\n      items: [\n        { title: 'Option 1' },\n        { title: 'Option 2' },\n        { title: 'Option 3' },\n        { title: 'Option 4' },\n      ],\n    }),\n  }\n</script>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":530,"y":120,"wires":[["85ddcad5226e744c"]]},{"id":"85ddcad5226e744c","type":"debug","z":"be4568a984cb4685","g":"2086b1f86b7ea9cc","name":"debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":120,"wires":[]},{"id":"58866c432c8047e0","type":"ui-template","z":"be4568a984cb4685","g":"2086b1f86b7ea9cc","group":"48fc19d1161f11e6","page":"","ui":"","name":"with icons","order":9,"width":"3","height":"1","head":"","format":"<template>\n  <div class=\"d-flex justify-space-around\">\n    <v-menu>\n      <template v-slot:activator=\"{ props }\">\n        <v-btn block color=\"primary\" v-bind=\"props\">\n          Select Option 2\n        </v-btn>\n      </template>\n      <v-list>\n        <v-list-item-group v-if=\"items.length > 0\">\n          <v-list-item v-for=\"(item, index) in items\" :key=\"index\" :value=\"index\"\n            @click=\"send({ payload: item.title })\">\n            <v-list-item-content class=\"d-flex align-center\">\n              <v-list-item-avatar>\n                <!-- Use the icon specified in the item object -->\n                <v-icon>{{ item.icon }}</v-icon>\n              </v-list-item-avatar>\n              <v-list-item-title class=\"text-h6\">{{ item.title }}</v-list-item-title>\n            </v-list-item-content>\n          </v-list-item>\n        </v-list-item-group>\n        <v-list-item v-else>\n          <v-list-item-content>No items available</v-list-item-content>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n  </div>\n</template>\n\n<script>\n  export default {\n  data: () => ({\n    items: [\n      { title: 'Option 1', icon: 'mdi-check' },\n      { title: 'Option 2', icon: 'mdi-account' },\n      { title: 'Option 3', icon: 'mdi-star' },\n      { title: 'Option 4', icon: 'mdi-alert' },\n    ],\n  }),\n};\n</script>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":540,"y":160,"wires":[["6a5445d93e54827e"]]},{"id":"6a5445d93e54827e","type":"debug","z":"be4568a984cb4685","g":"2086b1f86b7ea9cc","name":"debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":160,"wires":[]},{"id":"9161cc515f695ecd","type":"ui-template","z":"be4568a984cb4685","g":"2086b1f86b7ea9cc","group":"48fc19d1161f11e6","page":"","ui":"","name":"with url","order":10,"width":"3","height":"1","head":"","format":"<template>\n  <div class=\"d-flex justify-space-around\">\n    <v-menu>\n      <template v-slot:activator=\"{ props }\">\n        <v-btn block color=\"primary\" v-bind=\"props\">\n          Select Option 3\n        </v-btn>\n      </template>\n      <v-list>\n          <v-list-item v-for=\"(item, index) in items\" :key=\"index\" :value=\"index\" @click=\"send({ payload: item.url })\">\n            <v-list-item-content class=\"d-flex align-center\">\n              <v-list-item-avatar>\n                <!-- Use the icon specified in the item object -->\n                <v-icon>{{ item.icon }}</v-icon>\n              </v-list-item-avatar>\n              <v-list-item-title class=\"text-h6\">{{ item.title }}</v-list-item-title>\n            </v-list-item-content>\n          </v-list-item>\n      </v-list>\n    </v-menu>\n  </div>\n</template>\n\n<script>\n  export default {\n  data: () => ({\n    items: [\n      { title: 'Option 1', icon: 'mdi-check', url: 'https://example.com/option1' },\n      { title: 'Option 2', icon: 'mdi-account', url: 'https://example.com/option2' },\n      { title: 'Option 3', icon: 'mdi-star', url: 'https://example.com/option3' },\n      { title: 'Option 4', icon: 'mdi-alert', url: 'https://example.com/option4' },\n    ],\n  }),\n};\n</script>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":540,"y":200,"wires":[["f69abba39561daef"]]},{"id":"f69abba39561daef","type":"debug","z":"be4568a984cb4685","g":"2086b1f86b7ea9cc","name":"debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":200,"wires":[]},{"id":"48fc19d1161f11e6","type":"ui-group","name":"Test","page":"19eb6d108e9275e2","width":"20","height":"13","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"19eb6d108e9275e2","type":"ui-page","name":"Examples","ui":"ae3d4aeb3f977a90","path":"/examples","icon":"","layout":"tabs","theme":"a965ccfef139317a","order":3,"className":"","visible":true,"disabled":"false"},{"id":"ae3d4aeb3f977a90","type":"ui-base","name":"Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"temporary","titleBarStyle":"default"},{"id":"a965ccfef139317a","type":"ui-theme","name":"Default","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

Just to add to Steve's answer, we also have some template examples that use the Vuetify widgets too in the docs here:

Thanks all for the answers. Really useful - I can see it's going to be easy to use - just needed that little pointer to get me started.

1 Like

We're to help :+1:

Ok so I have this:

<v-slider v-model="value.setting.brightness" :min="0" :max="100" :step="value.resolution" @change="send({sysaction: 'bri', topic: key, brightness: value.setting.brightness, zone: msg.zoneid})" />

The slider is rendering correctly and binding to the input value, however no message is being sent out when I move the slider.

What have I done wrong?

Annoyingly, it seems like the v-slider doesn't emit a @change event: https://vuetifyjs.com/en/api/v-slider/#api

The alternative, and universal method is to react to changes to the v-model, which isn't intuitive to write, but does work across all widgets, which is:

@update:modelValue="send(...)"

Thanks - and here's one more. It doesn't send anything on the output. Did I get the syntax wrong?

<v-color-picker v-if="value.controltype == '3_RGB'" v-model="value.colour" hide-canvas show-swatches @change="send({sysaction: 'col', topic: key, colour: value.colour, zone: msg.zoneid})" mode="hexa" />

(Ignore the v-if, that works fine. In cases where that evaluates to true, the colour picker is shown ok. It just doesn't output anything.)

You should check the docs. Like the one above, color picker doesn't have an event change: https://vuetifyjs.com/en/api/v-color-picker/

Alternatively, bind the value to a data property and use a watch. Similar topic here: Dashboard 2 - VUE <v-color-picker> - #2 by Steve-Mcl

Thanks for the pointer. Got it working now. I thought I had read the docs but I was looking in the wrong place (was looking at this page). Cheers.

1 Like

Another question.

I often find myself getting something wrong which seems to crash Dashboard 2.0. For example, I make some error in the syntax of a template node, and then when I switch tabs in my browser to see the result in dashboard and hit Ctrl-R to refresh, I get a "loading" image in the middle of the page:
image

So then I'll go back to Node-RED and revert my changes then attempt to re-load, but I continue to get that loading image. Eventually I'll get this page display error in chrome: ""Error code: Out of Memory", at which point I can refresh the page and it loads again fine.

Is there some timeout I can change, or some way of forcing Dashboard 2.0 to restart somehow, to speed up this process?

Thanks

Generally it is the browser that is hung. The best thing is to close the tab, though even that may be difficult, and open a new one. At times I have had to close the whole browser.

Yeah, normally this is an infinite loop or something like that in your template, where the browser just gets completely consumed by it/ It's not anything we can control from within Dashboard unfortunately.

The editor in Node-RED supporting Vue syntax highlighting and linting would be a major improvement, but this is not straight forward as @Steve-Mcl can detail.

Just checking we are talking about the same thing: Node-RED isn't crashing, Dashboard 1 works ok it's just the Dashboard 2.0 page that renders the "not responding", so I wondered if there was some way of resetting Dashboard 2.0.

I'll do what @Colin suggested as I hadn't thought about it being a browser hang. Will test.

Yes, sorry, I was essentially agreeing with Colin.

I suspect its an error in the ui-template code, when the browser tries to render it (in Dashboard), it hangs.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.