# Dashboard 2 change icon

**URL:** <https://discourse.nodered.org/t/dashboard-2-change-icon/85005>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [29 January 2024 02:18 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005 "2024-01-29T02:18:41Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![gerry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gerry/32/21604_2.png) [@gerry](https://discourse.nodered.org/u/gerry)\
**Post date:** [29 January 2024 02:18 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/1 "2024-01-29T02:18:41Z")

</div>

Started trying out Dashboard 2 and have what I think must be an easy problem but it totally eludes me.  
Using the standard template I am trying to change an icon color programmatically. here is my flow

```auto
[{"id":"8960b0e31897e48b","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"58678123cf0c29b5","type":"ui-template","z":"8960b0e31897e48b","group":"590d5f457d16fcac","page":"","ui":"","name":"","order":0,"width":"6","height":"5","head":"","format":"<template>\n <div>\n <h2>Counter</h2>\n <p class=\"a1\">Current Count: {{ count }}</p>\n <p class=\"my-class\">Formatted Count: {{ color }}</p>\n <v-btn @click=\"increase()\">{{mycolor}}</v-btn>\n <v-btn class=\"blank\" @click=\"decrease()\">Decrement</v-btn>\n <v-btn class=\"blank\" @click=\"decrease()\">Dn<v-icon right dark color={{color}}>mdi-arrow-down</v-icon></v-btn> \n <v-btn class=\"blank1\" @click=\"increase()\">Up<v-icon right dark color=\"red\">mdi-arrow-up</v-icon></v-btn>\n \n </div>\n</template>\n\n<script>\n export default {\n data() {\n // define variables available component-wide\n // (in <template> and component functions)\n return {\n count: 10,\n mycolor: \"red\",\n }\n },\n watch: {\n // watch for any changes of \"count\"\n count: function () {\n if (this.count % 5 === 0) {\n this.send({payload: 'Multiple of 5'})\n }\n }\n },\n computed: {\n // automatically compute this variable\n // whenever VueJS deems appropriate\n formattedCount: function () {\n return this.count + ' Cherries'\n }\n },\n methods: {\n // expose a method to our <template> and Vue Application\n increase: function () {\n this.count++\n this.send({payload: 'plus',\n topic: 'up'})\n if (this.count > 22){\n this.count=22 \n }\n },\n decrease: function () {\n this.count--\n this.send({payload: 'minus',\n topic: 'dn'})\n if (this.count < 10) {\n this.count = 10\n }\n }\n },\n mounted() {\n // code here when the component is first loaded\n this.color = \"red\"\n },\n unmounted() {\n // code here when the component is removed from the Dashboard\n // i.e. when the user navigates away from the page\n }\n }\n</script>\n<style>\n /* define any styles here - supports raw CSS */\n .my-class {\n color: red;\n }\n .your-class {\n color: green\n }\n.centerme {\ndisplay: flex;\ntext-align: center;\njustify-content: center;\nalign-items: center;\nmargin: 4px;\n}\n\n.roundme {\nborder: 2px solid black;\nborder-radius: 8px;\nbackground-color: #222222;\nbox-shadow: inset 2px 2px 3px 4px rgba(0, 0, 0, 0.1);\nbackground: rgb(5, 5, 5);\nbackground: linear-gradient(135deg, rgba(5, 5, 5, 1) 0%, rgba(42, 42, 42, 1) 100%);\nmargin: 3px;\n}\n\n.roundme2 {\nborder: 2px solid black;\nborder-radius: 8px;\nbackground-color: #222222;\nbox-shadow: inset 2px 2px 3px 4px rgba(0, 0, 0, 0.1);\nbackground: rgb(5, 5, 5);\nmargin: 3px;\n}\n\n.blank {\nborder: #303030;\nborder-radius: 8px;\nbackground-color: #303030;\nbox-shadow: inset 2px 2px 3px 4px #303030;\nbackground: #303030;\nbackground: linear-gradient(135deg, #303030 0%, #303030);\nmargin: 3px;\n}\n\n.blank1 {\nborder: #FF0000;\nborder-radius: 8px;\nbackground-color: #FF0000;\nbox-shadow: inset 2px 2px 2px 2px #FF0000;\nbackground: #303030;\nbackground: linear-gradient(135deg, #303030 0%, #303030);\nmargin: 3px;\n}\n.a {\n/* background-color:red; */\nheight: 25px;\nmargin-bottom: 1px;\nfont-size: 16px;\nfont-color: #000000;\npadding-bottom: 4px;\nborder-bottom: 2px solid #DD7F00;\n}\n\n.a1 {\n/* background-color:red; */\nheight: 25px;\nmargin-bottom: 1px;\nfont-size: 16px;\ncolor: #6689A1;\npadding-bottom: 4px;\nborder-bottom: 2px solid #DD7F00;\n}\n\n.a2 {\n/* background-color:red; */\nheight: 100%;\nmargin-top: 1px;\nfont-size: 60px;\ncolor: #D7DBDD;\n\n}\n\n.b1 {\ncolor: #6689A1;\nheight: 25px;\nmargin-bottom: 1px;\nfont-size: 16px;\npadding-bottom: 4px;\nborder-bottom: 2px solid #DD7F00;\n}\n\n.b2 {\nheight: 100%;\nmargin-top: 1px;\nfont-size: 28px;\ncolor: #D7DBDD;\n}\n\n.gradient-2 {\nbackground: linear-gradient(135deg, rgba(5, 5, 5, 1) 0%, rgba(42, 42, 42, 1) 100%) padding-box,\nlinear-gradient(to right, #F16F0F, #F43700) border-box;\nmargin-top: 14px;\nborder-radius: 20px;\nborder: 6px solid transparent;\n}\n\n.red_color {\ncolor: #FF0000;\n}\n\n.grey_color {\ncolor: #444444;\n}\n\n.green_color {\ncolor: #008000;\n}\n\n.blue_color {\ncolor: #00DAF4;\n}\n\n\n.otstatus {\npadding-left: 6px;\npadding-top: 2px;\nfont-size: 14px;\n}\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":400,"y":80,"wires":[["bffcce078a372ce8"]]},{"id":"bffcce078a372ce8","type":"debug","z":"8960b0e31897e48b","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":360,"y":180,"wires":[]},{"id":"590d5f457d16fcac","type":"ui-group","name":"Page1","page":"efac97e4288db043","width":"6","height":"4","order":-1,"showTitle":false,"className":"","visible":"true","disabled":"false"},{"id":"efac97e4288db043","type":"ui-page","name":"Page1","ui":"22de1f06fe4a8c37","path":"/page1","icon":"home","layout":"grid","theme":"af27d8bd1af493a2","order":-1,"className":"","visible":"true","disabled":"false"},{"id":"22de1f06fe4a8c37","type":"ui-base","name":"path","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"af27d8bd1af493a2","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

```

when I open the page I would think the color would change, but nothing seems to work. When I click on a button then the word red appears in the formatted count field but the icon doesn't change no matter what I have tried. Point me in the right direction please?

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [30 January 2024 00:07 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/2 "2024-01-30T00:07:25Z")

</div>

This is probably more than you wanted but it demonstrates changing icon colour

```auto
[{"id":"b3fae0cdaf1aa48b","type":"inject","z":"506727cd93754bdb","g":"f80590b4d4630047","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"ui-property: sliderRange","payload":"{\"min\": 1, \"max\": 50}","payloadType":"json","x":710,"y":860,"wires":[["c7b6dd708fbf3d12"]]},{"id":"c7b6dd708fbf3d12","type":"ui-template","z":"506727cd93754bdb","g":"f80590b4d4630047","group":"0a0ba0877032ca64","page":"","ui":"","name":"Icon Button","order":0,"width":0,"height":0,"head":"","format":"<template>\n <v-card class = \"card\">\n <v-btn class = \"btnBasic\" :class = \"btnClass\" stacked @click=\"changeState()\">\n {{btnText}}\n <v-icon class = \"iconBasic\" :class = \"iconClass\" >mdi-lightbulb-variant-outline</v-icon> \n \n </v-btn>\n \n <v-slider\n v-model=\"sliderValue\"\n width=\"50\" \n :min=\"sliderRange.min\" \n :max=\"sliderRange.max\" \n thumb-size=\"12\"\n :color = \"sliderColour\"\n @end=\"updateSlider()\">\n </v-slider>\n\n </v-card>\n\n</template>\n\n<script>\n export default {\n data() {\n return {\n btnState: 0,\n\n\t\t\t\tbtnData: {class: ['btnOff', 'btnOn'], text: ['Light']},\n iconData: {class: ['iconOff', 'iconOn']},\n\n outputValue: ['Off', 'On'],\n\n sliderColour: 'orange',\n sliderValue: 0,\n sliderRange: {min: 1, max: 100},\n\t\n }\n\t\n },\n \n methods: {\n changeState: function () {\n\t\t\t\tthis.toggleState(this.btnState)\n\n\t\t\t\tthis.send(this.outputValue[this.btnState])\n //this.send({topic: \"Button Out\", payload: this.outputValue[this.btnState]})\n\n },\n\t\n toggleState: function () { \n this.btnState = (++this.btnState) % this.outputValue.length\n\n // Slider starts at 1 if Button 'On', reset to 0 if Button is 'Off'\n\t\t\t\tthis.sliderValue = this.btnState\n \n },\n\n updateSlider: function () {\n if (this.btnState === 1) {\n this.send( parseInt(this.sliderValue) )\n\n } else {\n this.sliderValue = 0\n\n } \n },\n\t\t\t\n },\n\n watch: {\n\n },\n\n computed: {\n // automatically compute this variable\n // whenever VueJS deems appropriate\n btnText: function() {\n let buttonText = this.btnData.text[0]\n if (this.btnData.text.length > this.btnState) {\n buttonText = this.btnData.text[this.btnState]\n }\n\n return buttonText\n \n },\n\n btnClass: function() {\n return (this.btnState === 0) ? this.btnData.class[0] : this.btnData.class[1]\n\n },\n\t\t\t\n iconClass: function() {\n return (this.btnState === 0) ? this.iconData.class[0] : this.iconData.class[1]\n\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-property: <property>,\n * payload: \"<value>\"\n * \n */\n const payloadValue = msg.payload\n\n if (!msg.topic.includes('ui-property')) {\n // msg.payload can be 0 or 1, or values of button text\n if ((typeof payloadValue === 'string') || (payloadValue instanceof String)) {\n const index = outputValue.findIndex((element) => element.toLowerCase() === payloadValue.toLowerCase())\n // Nothing happens if payloadValue not found\n if (index >= 0) this.btnState = index\n\n } else if (typeof payloadValue === 'number' && isFinite(payloadValue)) {\n const maxValue = this.outputValue.length - 1\n const minValue = 0\n\n // Set btnState to payloadValue, or min or max if payloadValue < min or > max\n this.btnState = Math.min(maxValue, Math.max(payloadValue, minValue))\n\n }\n\n } else {\n\n this.send(payloadValue)\n /** Update Widget values if required\n * \n * Input ui-property payload <value>\n * buttonText Array of string, length 1 or more. Only number of outputValues\n * will be shown\n * output Array of output values (any), length 1 or more. Each 'click' of\n * button will output next value in Array. Button text will also\n * update for each 'click' if there is more than 1 string in btnData.text\n * Array\n * sliderRange Object, {min: <minValue>, max: <maxValue>}\n * sliderColour Slider color, (both track & thumb) \n * \n * msgPassThrough If true incoming msg is passed through, otherwise not\n * \n */\n \n const property = msg.topic.split(':')[1].trim()\n\n if (property === 'buttonText') this.btnData.text = payloadValue\n if (property === 'output') this.outputValue = payloadValue\n\n if (property === 'sliderRange') this.sliderRange = payloadValue\n if (property === 'sliderColour') this.sliderColour = payloadValue\n\n /**\n this.btnData.text = msg?.buttonText ?? this.btnData.text\n this.outputValue = msg?.output ?? this.outputValue\n this.sliderRange = msg?.sliderRange ?? this.sliderRange\n this.sliderColour = msg?.sliderColour ?? this.sliderColour\n\n */\n\n }\n\n })\n\n },\n\n unmounted() {\n // code here when the component is removed from the Dashboard\n // i.e. when the user navigates away from the page\n this.$socket.off(`msg-input:${this.id}`)\n },\n\n }\n\n</script>\n\n<style scoped>\n .card {\n background-color: #4F4F4F; /* Very dark gray */\n border: 1px solid black; \n border-radius: 8px; \n width: 75px !important;\n height: 105px;\n\n }\n\n .btnBasic {\n background-color: #4F4F4F; /* Very dark gray */\n border-radius: 8px;\n /*width: 75px !important;*/\n height: 75px !important;\n\n }\n\n\t.btnOn {\n color: rgb(189, 150, 8); /* Dark washed rose */\n\n\t}\n\t\n\t.btnOff {\n\t\tcolor: darkgrey;\n\n\t}\n\n\t.iconBasic {\n\t\tfont-size: 45px;\n height: 45px;\n width: 45px;\n\n\t}\n\n\t.iconOn {\n color: rgb(189, 150, 8); /* Dark washed rose */\n text-shadow: rgb(189, 150, 8) 0px 0px 10px; /* Dark washed rose */\n\n\t}\n\t\n\t.iconOff {\n\t\tcolor: darkgrey;\n\t\ttext-shadow: 0px 0px 0px;\n\n\t}\n\n .v-slider-thumb__surface{\n background-color: currentColor;\n\n }\n\n</style>","storeOutMessages":true,"passthru":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":1050,"y":860,"wires":[["8f30da685c1e89e4"]],"info":" :color = \"sliderColour\"\r\n\r\n thumb-color = \"red\"\r\n track-color=\"green\" "},{"id":"8f30da685c1e89e4","type":"debug","z":"506727cd93754bdb","g":"f80590b4d4630047","name":"Icon Button","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1430,"y":860,"wires":[]},{"id":"0a0ba0877032ca64","type":"ui-group","name":"Icon Button","page":"79a8176801c89202","width":"6","height":"1","order":-1,"showTitle":true,"className":""},{"id":"79a8176801c89202","type":"ui-page","name":"Page 05","ui":"b810194ea14e3502","path":"/page05","layout":"grid","theme":"62307b5371f6467e","order":-1,"className":""},{"id":"b810194ea14e3502","type":"ui-base","name":"Various Dashboard 2 Examples","path":"/dashboard"},{"id":"62307b5371f6467e","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}]

```

---

<div class="post-metadata">

**Author:** ![gerry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gerry/32/21604_2.png) [@gerry](https://discourse.nodered.org/u/gerry)\
**Post date:** [30 January 2024 03:09 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/3 "2024-01-30T03:09:34Z")

</div>

@Buckskin, sorry, I got the page loaded see the light bulb icon but if I move the slider it goes back to the left and the icon never changes color, if I use the inject node I don't see any change, if I go back to the page it still doesn't change icon, sorry, apparently I don't know how to use your flow.

---

<div class="post-metadata">

**Author:** ![gerry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gerry/32/21604_2.png) [@gerry](https://discourse.nodered.org/u/gerry)\
**Post date:** [30 January 2024 03:17 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/4 "2024-01-30T03:17:14Z")

</div>

Ok, if I just click the button the icon changes so I can work with that. Thanks. will try to understand what's happening.

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [30 January 2024 09:24 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/5 "2024-01-30T09:24:22Z")

</div>

The slider only works once the button is clicked. I 'borrowed' the original from someo ne else 😉

---

<div class="post-metadata">

**Author:** ![TheSaltydog](https://avatars.discourse-cdn.com/v4/letter/t/47e85d/32.png) [@TheSaltydog](https://discourse.nodered.org/u/TheSaltydog)\
**Post date:** [30 January 2024 10:20 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/6 "2024-01-30T10:20:07Z")

</div>

I think this can be merged in a subflow "Toggle Button", with env variables to set colors, dimension, icon, etc...

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [13 February 2024 10:20 UTC](https://discourse.nodered.org/t/dashboard-2-change-icon/85005/7 "2024-02-13T10:20:22Z")

</div>

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