Dashboard 2 change icon

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

[{"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?

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

[{"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"}}]

@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.

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

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

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

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