How to create a working round color picker (iro.js) in Node-RED Dashboard 2.0

Hello,

I want to use a round or hexagonal color picker in Node-RED Dashboard 2.0 (like with iro.js), but I can't seem to get it to work properly. The color picker itself is sometimes shown in the dashboard and sometimes not, and I don't get any data (like the chosen color) back in Node-RED.
My goal is to use this color to control a light, so the color black doesn't have to be in it.
I've tried sending the color back to a debug node via a ui_template node, but so far without success.
Does anyone have experience with a working solution or tips on how to best approach this in Dashboard 2.0?

Thanks in advance!

Hi. Firstly, there is already a colour picker in the ui-text-input.

If that is not suitable then please share your current flow and someone I'm sure will take a look.

PS have you checked the online dashboard documentation for the UI template? It details how to send messages back to node red server side.

Try this as a starter for 10

[{"id":"b08ccbf9c0cf044a","type":"group","z":"506727cd93754bdb","name":"Colour Picker","style":{"label":true},"nodes":["50e4b2edb03e48cb","d2e817fd4b68b289","adbd76ecf97076a1","b9d77a856b1be020","294ac777d99f5789","cd624053824f0e11"],"x":34,"y":2279,"w":672,"h":222},{"id":"50e4b2edb03e48cb","type":"ui-template","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","group":"da61a9db1323ae79","page":"","ui":"","name":"Colour Picker","order":1,"width":"3","height":"3","head":"","format":"<template>\n  <div class = \"d-flex flex-column\">\n    <div>Choose a Colour</div>\n    \n    <v-color-picker\n      class = \"ma-2\"\n      v-model = \"colourChoice\"\n      v-model:mode = \"mode\"\n      hide-canvas\n      hide-sliders\n      hide-inputs\n      :swatches = \"swatches\"\n      show-swatches\n    ></v-color-picker>\n  \n  </div>\n\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      colourChoice: { h: 300, s: 1, v: 1, a: 1 },\n      mode: 'hsva',\n      swatches: [\n        ['#FF0000', '#AA0000', '#550000'],\n        ['#FFFF00', '#AAAA00', '#555500'],\n        ['#00FF00', '#00AA00', '#005500'],\n        ['#00FFFF', '#00AAAA', '#005555'],\n        ['#0000FF', '#0000AA', '#000055'],\n   \n      ],\n\n    }\n\n  },\n\n  watch: { \n    colourChoice: function () {\n      this.send({colour: this.colourChoice})\n\n    },\n\n  },\n\n  methods: {\n \n  },\n\n  computed : {\n \n\n  },\n\n    mounted () {               \n      this.$socket.on(\"msg-input:\" + this.id, (msg) => {\n        /**\n        * Comply with Dashboard 2 schema to set dynamic values\n        * \n        * topic:     ui_update: <property>,\n        * payload:   \"<value>\"\n        * \n        */\n          if (typeof msg?.ui_update?.colour === \"string\") {\n            this.colourChoice = msg.ui_update.colour\n\n          }\n  \n      })\n\n    },\n\n}\n</script>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":180,"y":2320,"wires":[["adbd76ecf97076a1","cd624053824f0e11"]]},{"id":"d2e817fd4b68b289","type":"debug","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Colour Choice","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":580,"y":2320,"wires":[]},{"id":"adbd76ecf97076a1","type":"change","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Hide Dialog","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"groups\":{\"hide\":[\"Colour Picker:Dialog Group\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":2420,"wires":[["b9d77a856b1be020"]]},{"id":"b9d77a856b1be020","type":"debug","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Colour Picker \\n Dialog Out","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":420,"y":2440,"wires":[]},{"id":"294ac777d99f5789","type":"ui-button","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","group":"50a1affd15cb19af","name":"","label":"Colour Picker <br> (Dialog)","order":1,"width":"1","height":"1","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"{\"groups\":{\"show\":[\"Colour Picker:Dialog Group\"]}}","payloadType":"json","topic":"topic","topicType":"msg","buttonColor":"","textColor":"","iconColor":"","enableClick":true,"enablePointerdown":false,"pointerdownPayload":"","pointerdownPayloadType":"str","enablePointerup":false,"pointerupPayload":"","pointerupPayloadType":"str","x":180,"y":2460,"wires":[["b9d77a856b1be020"]]},{"id":"cd624053824f0e11","type":"change","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"","rules":[{"t":"set","p":"colour.s","pt":"msg","to":"msg.colour.s * 100","tot":"jsonata"},{"t":"set","p":"colour.v","pt":"msg","to":"msg.colour.v * 100","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":2320,"wires":[["d2e817fd4b68b289"]]},{"id":"da61a9db1323ae79","type":"ui-group","name":"Dialog Group","page":"964f6d397737c6ff","width":"3","height":1,"order":1,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"dialog"},{"id":"50a1affd15cb19af","type":"ui-group","name":"Colour Picker","page":"964f6d397737c6ff","width":"1","height":1,"order":2,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"964f6d397737c6ff","type":"ui-page","name":"Colour Picker","ui":"b810194ea14e3502","path":"/Colour-Picker","icon":"home","layout":"grid","theme":"5075a7d8e4947586","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":3,"className":"","visible":true,"disabled":false},{"id":"b810194ea14e3502","type":"ui-base","name":"Dashboard 2 Examples","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-control","ui-notification"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"5075a7d8e4947586","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"6px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}}]

Thanks for your code. I tested it and I see this:


I also see the chosen value appear in the debug. Can this also work for a round color picker?

Apologies, I left a bit out

[{"id":"b08ccbf9c0cf044a","type":"group","z":"506727cd93754bdb","name":"Colour Picker","style":{"label":true},"nodes":["50e4b2edb03e48cb","d2e817fd4b68b289","adbd76ecf97076a1","b9d77a856b1be020","294ac777d99f5789","cd624053824f0e11","1e13e4488e74526e"],"x":34,"y":2279,"w":672,"h":222},{"id":"50e4b2edb03e48cb","type":"ui-template","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","group":"da61a9db1323ae79","page":"","ui":"","name":"Colour Picker","order":1,"width":"3","height":"3","head":"","format":"<template>\n  <div class = \"d-flex flex-column\">\n    <div>Choose a Colour</div>\n    \n    <v-color-picker\n      class = \"ma-2\"\n      v-model = \"colourChoice\"\n      v-model:mode = \"mode\"\n      hide-canvas\n      hide-sliders\n      hide-inputs\n      :swatches = \"swatches\"\n      show-swatches\n    ></v-color-picker>\n  \n  </div>\n\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      colourChoice: { h: 300, s: 1, v: 1, a: 1 },\n      mode: 'hsva',\n      swatches: [\n        ['#FF0000', '#AA0000', '#550000'],\n        ['#FFFF00', '#AAAA00', '#555500'],\n        ['#00FF00', '#00AA00', '#005500'],\n        ['#00FFFF', '#00AAAA', '#005555'],\n        ['#0000FF', '#0000AA', '#000055'],\n   \n      ],\n\n    }\n\n  },\n\n  watch: { \n    colourChoice: function () {\n      this.send({colour: this.colourChoice})\n\n    },\n\n  },\n\n  methods: {\n \n  },\n\n  computed : {\n \n\n  },\n\n    mounted () {               \n      this.$socket.on(\"msg-input:\" + this.id, (msg) => {\n        /**\n        * Comply with Dashboard 2 schema to set dynamic values\n        * \n        * topic:     ui_update: <property>,\n        * payload:   \"<value>\"\n        * \n        */\n          if (typeof msg?.ui_update?.colour === \"string\") {\n            this.colourChoice = msg.ui_update.colour\n\n          }\n  \n      })\n\n    },\n\n}\n</script>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":180,"y":2320,"wires":[["adbd76ecf97076a1","cd624053824f0e11"]]},{"id":"d2e817fd4b68b289","type":"debug","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Colour Choice","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":580,"y":2320,"wires":[]},{"id":"adbd76ecf97076a1","type":"change","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Hide Dialog","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"groups\":{\"hide\":[\"Colour Picker:Dialog Group\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":2420,"wires":[["b9d77a856b1be020","1e13e4488e74526e"]]},{"id":"b9d77a856b1be020","type":"debug","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Colour Picker \\n Dialog Out","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":420,"y":2440,"wires":[]},{"id":"294ac777d99f5789","type":"ui-button","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","group":"50a1affd15cb19af","name":"","label":"Colour Picker <br> (Dialog)","order":1,"width":"1","height":"1","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"{\"groups\":{\"show\":[\"Colour Picker:Dialog Group\"]}}","payloadType":"json","topic":"topic","topicType":"msg","buttonColor":"","textColor":"","iconColor":"","enableClick":true,"enablePointerdown":false,"pointerdownPayload":"","pointerdownPayloadType":"str","enablePointerup":false,"pointerupPayload":"","pointerupPayloadType":"str","x":180,"y":2460,"wires":[["b9d77a856b1be020","1e13e4488e74526e"]]},{"id":"cd624053824f0e11","type":"change","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"","rules":[{"t":"set","p":"colour.s","pt":"msg","to":"msg.colour.s * 100","tot":"jsonata"},{"t":"set","p":"colour.v","pt":"msg","to":"msg.colour.v * 100","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":2320,"wires":[["d2e817fd4b68b289"]]},{"id":"1e13e4488e74526e","type":"ui-control","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"","ui":"b810194ea14e3502","events":"all","x":400,"y":2380,"wires":[[]]},{"id":"da61a9db1323ae79","type":"ui-group","name":"Dialog Group","page":"964f6d397737c6ff","width":"3","height":1,"order":1,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"dialog"},{"id":"50a1affd15cb19af","type":"ui-group","name":"Colour Picker","page":"964f6d397737c6ff","width":"1","height":1,"order":2,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"b810194ea14e3502","type":"ui-base","name":"Dashboard 2 Examples","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-control","ui-notification"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"964f6d397737c6ff","type":"ui-page","name":"Colour Picker","ui":"b810194ea14e3502","path":"/Colour-Picker","icon":"home","layout":"grid","theme":"5075a7d8e4947586","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":3,"className":"","visible":true,"disabled":false},{"id":"5075a7d8e4947586","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"6px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}}]

You should see the button, then when pressed the dialog which then disappears when a colour selected.

This should give you round swatch selectors. See the at the bottom of the colour picker node. .v-color-picker-swatches__color seems to control the size & shape of the swatch selectors.

[{"id":"b08ccbf9c0cf044a","type":"group","z":"506727cd93754bdb","name":"Colour Picker","style":{"label":true},"nodes":["50e4b2edb03e48cb","d2e817fd4b68b289","adbd76ecf97076a1","b9d77a856b1be020","294ac777d99f5789","cd624053824f0e11","1e13e4488e74526e"],"x":34,"y":2279,"w":672,"h":222},{"id":"50e4b2edb03e48cb","type":"ui-template","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","group":"da61a9db1323ae79","page":"","ui":"","name":"Colour Picker","order":1,"width":"3","height":"3","head":"","format":"<template>\n  <div class = \"d-flex flex-column\">\n    <div>Choose a Colour</div>\n    \n    <v-color-picker\n      class = \"ma-2\"\n      v-model = \"colourChoice\"\n      v-model:mode = \"mode\"\n      hide-canvas\n      hide-sliders\n      hide-inputs\n      :swatches = \"swatches\"\n      show-swatches\n    ></v-color-picker>\n  \n  </div>\n\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      colourChoice: { h: 300, s: 1, v: 1, a: 1 },\n      mode: 'hsva',\n      swatches: [\n        ['#FF0000', '#AA0000', '#550000'],\n        ['#FFFF00', '#AAAA00', '#555500'],\n        ['#00FF00', '#00AA00', '#005500'],\n        ['#00FFFF', '#00AAAA', '#005555'],\n        ['#0000FF', '#0000AA', '#000055'],\n   \n      ],\n\n    }\n\n  },\n\n  watch: { \n    colourChoice: function () {\n      this.send({colour: this.colourChoice})\n\n    },\n\n  },\n\n  methods: {\n \n  },\n\n  computed : {\n \n\n  },\n\n    mounted () {               \n      this.$socket.on(\"msg-input:\" + this.id, (msg) => {\n        /**\n        * Comply with Dashboard 2 schema to set dynamic values\n        * \n        * topic:     ui_update: <property>,\n        * payload:   \"<value>\"\n        * \n        */\n          if (typeof msg?.ui_update?.colour === \"string\") {\n            this.colourChoice = msg.ui_update.colour\n\n          }\n  \n      })\n\n    },\n\n}\n</script>\n\n<style>\n  .v-color-picker-swatches__color {\n    height:32px;\n    max-height: 32px;\n    width:32px;\n    border-radius: 16px;\n  }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":180,"y":2320,"wires":[["adbd76ecf97076a1","cd624053824f0e11"]]},{"id":"d2e817fd4b68b289","type":"debug","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Colour Choice","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":580,"y":2320,"wires":[]},{"id":"adbd76ecf97076a1","type":"change","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Hide Dialog","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"groups\":{\"hide\":[\"Colour Picker:Dialog Group\"]}}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":2420,"wires":[["b9d77a856b1be020","1e13e4488e74526e"]]},{"id":"b9d77a856b1be020","type":"debug","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"Colour Picker \\n Dialog Out","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":420,"y":2440,"wires":[]},{"id":"294ac777d99f5789","type":"ui-button","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","group":"50a1affd15cb19af","name":"","label":"Colour Picker <br> (Dialog)","order":1,"width":"1","height":"1","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"{\"groups\":{\"show\":[\"Colour Picker:Dialog Group\"]}}","payloadType":"json","topic":"topic","topicType":"msg","buttonColor":"","textColor":"","iconColor":"","enableClick":true,"enablePointerdown":false,"pointerdownPayload":"","pointerdownPayloadType":"str","enablePointerup":false,"pointerupPayload":"","pointerupPayloadType":"str","x":180,"y":2460,"wires":[["b9d77a856b1be020","1e13e4488e74526e"]]},{"id":"cd624053824f0e11","type":"change","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"","rules":[{"t":"set","p":"colour.s","pt":"msg","to":"msg.colour.s * 100","tot":"jsonata"},{"t":"set","p":"colour.v","pt":"msg","to":"msg.colour.v * 100","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":2320,"wires":[["d2e817fd4b68b289"]]},{"id":"1e13e4488e74526e","type":"ui-control","z":"506727cd93754bdb","g":"b08ccbf9c0cf044a","name":"","ui":"b810194ea14e3502","events":"all","x":400,"y":2380,"wires":[[]]},{"id":"da61a9db1323ae79","type":"ui-group","name":"Dialog Group","page":"964f6d397737c6ff","width":"3","height":1,"order":1,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"dialog"},{"id":"50a1affd15cb19af","type":"ui-group","name":"Colour Picker","page":"964f6d397737c6ff","width":"1","height":1,"order":2,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"b810194ea14e3502","type":"ui-base","name":"Dashboard 2 Examples","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-control","ui-notification"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":5,"showDisconnectNotification":true,"allowInstall":true},{"id":"964f6d397737c6ff","type":"ui-page","name":"Colour Picker","ui":"b810194ea14e3502","path":"/Colour-Picker","icon":"home","layout":"grid","theme":"5075a7d8e4947586","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":3,"className":"","visible":true,"disabled":false},{"id":"5075a7d8e4947586","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"6px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}}]

Note: Color picker component — Vuetify shows how to change the colour mode so you can pick a different output colour mode.

1 Like