Change some display properties of template from incoming msg

Hi everyone,

I'm using one of the great meters examples from @hotNipi , thanks a lot to him for all of his great work !!

the plan is to use a meter like this one, and I try to change the colors property of the template, so I can turn the meter color greyed when channel is disabled :

I tried a few different things , like this.colors = this.msg.colors in watch , playing with the "mounted" section of script, but nothing helps. Could someone give me some advice ?

The alternate colors could be either set in the template itself and triggered from a incoming msg property , or directly passed to template as a msg.colors, I don't care....

Here is the code :

[
    {
        "id": "ca976be470bdfe6c",
        "type": "ui-template",
        "z": "1b6a54cdaa6bce06",
        "group": "c82ecbea129ea0dc",
        "page": "",
        "ui": "",
        "name": "meter",
        "order": 12,
        "width": "2",
        "height": "1",
        "head": "",
        "format": "<template>\n    <div class=\"led-level\">\n        <div :class=\"icon ? 'led-level-grid-2':'led-level-grid-1'\">\n            <div v-if=\"icon\" class=\"led-level-icon\">\n                <v-icon aria-hidden=\"false\">{{icon}}</v-icon>\n            </div>\n            <div class=\"led-level-content\">\n                <div class=\"led-level-text\">\n                    <span class=\"led-level-label\">{{msg.name}}</span>\n                    <span class=\"led-level-value\">{{formattedValue}}<span class=\"led-level-unit\">{{unit}}</span></span>\n                </div>\n                <div class=\"led-level-stripe\">\n                    <div v-for=\"(color, index) in colors\" :key=\"index\" class=\"led-level-led\" :ref=\"'dot-' + index\">\n                    </div>\n                </div>\n                <div class=\"led-level-limits\">\n                    <span class=\"led-level-limit\">{{min}}</span>\n                    <span v-for=\"(tick, index) in ticks\" :key=\"index\" class=\"led-level-limit\" :ref=\"'tick-' + index\"></span>\n                    <span class=\"led-level-limit\">{{max}}</span>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n<script>\n    export default {\n    data(){\n        return {\n            //Define me here\n                                               \n            label:\"Level long name\", // The label\n            icon:\"mdi-audio-input-rca\", //mdi-account (optional) the icon           \n            min:-50, // Smallest expected value\n            max:10, // Highest expected value\n            unit:\"dB\",// The unit of the measurement\n            dim:0.2, //How dim is led when not glowing \n            \n            animate:true, // Animating led's is not most performant thing in the world. \n\n        colors:[ \n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\",\n                \"#00e300\", \n                \"#ffa916\", \n                \"#ffa916\", \n                \"#ffa916\", \n                \"#ff4c16\",\n                \"#ff4c16\"],\n                \n                ticks:[50,75], //optional tick values          \n            //ticks:[\" \", \" \"]\n\n            //no need to change those\n            value:0,\n            previousValue:0,         \n            inited:false\n        }\n    },\n\n\n   \n    methods: {        \n        getElement: function(name,base){        \n            if(base){\n                return this.$refs[name]\n            }\n            return this.$refs[name][0]\n        },\n        validate(data){\n            let ret\n            if(typeof data !== \"number\"){\n                ret = parseFloat(data)\n                if(isNaN(ret)){\n                    console.log(\"BAD DATA! id:\",this.id,\"data:\",data)\n                    return null\n                }   \n            }\n            else{\n                ret = data\n            }            \n            return ret\n        },\n\n        full: function(){\n            return Math.floor(this.colors.length*this.percentage/100)\n        },\n        half: function (){\n            let p = this.colors.length*this.percentage/100;\n            p -= this.full()\n            p *= .5\n            p += this.dim;\n            return p;\n        },\n        \n        tickPosition: function(tv){\n        \n            return Math.floor(((tv - this.min) / (this.max - this.min)) * 100)+'%';\n        },\n        \n\n        lit: function(){\n            if(this.inited == false){\n                return\n            }\n            const down = this.previousValue > this.value\n            let time = down ? 1 : 0.2\n            let step = down ? 0.12 : 0.06\n            this.colors.forEach((color,i) => {\n                let dot = this.getElement(\"dot-\"+i);\n                if(!dot){\n                    console.log(\"lit() no dots found\")\n                    return\n                }                \n                if(i<this.full()){                   \n                    dot.style.opacity = 1;\n                    time += step\n                }\n                else if(i==this.full()){                    \n                    dot.style.opacity = this.half()                                   \n                }\n                else{                  \n                    dot.style.opacity = this.dim                                  \n                }\n                if(down){                  \n                    time -= step                                 \n                }\n                else{\n                    time -= step\n                }\n                dot.style.transition = this.animate && time > 0 ? \"opacity \"+time+\"s\" : \"unset\";\n            })\n            this.previousValue = this.value\n        }    \n    },\n    watch: {\n        msg: function(){    \n            if(this.msg.payload !== undefined){  \n                const v = this.validate(this.msg.payload)                \n                if(v === null){\n                    return\n                }         \n                this.value = v                \n                this.lit()\n                // log what is stored in msg after reload\n                console.log(\"Msg stored\", this.msg)\n                this.colors = this.msg.colors\n            }\n        }\n    },\n    computed: {\n        formattedValue: function () {\n            return this.value.toFixed(0)\n        },\n        percentage: function(){\n            return Math.floor(((this.value - this.min) / (this.max - this.min)) * 100);\n        }\n    },\n    mounted(){\n                this.colors.forEach((c,i) => {\n                let dot = this.getElement(\"dot-\"+i);\n                if(!dot){                        \n                    return\n                }                    \n                dot.style.backgroundColor = c                    \n            }\n        );\n         this.ticks.forEach((t,i) => {\n            let tick = this.getElement(\"tick-\"+i);\n                if(!tick){                        \n                    return\n                }                    \n                tick.style.left = this.tickPosition(t)\n            }\n        ); \n\n        this.inited = true;\n    },\n    unmounted () {\n       \n    }\n}\n</script>",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 560,
        "y": 840,
        "wires": [
            []
        ]
    },
    {
        "id": "d7991814a4797454",
        "type": "inject",
        "z": "1b6a54cdaa6bce06",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "name",
                "v": "Channel 1",
                "vt": "str"
            },
            {
                "p": "enabled",
                "v": "on",
                "vt": "str"
            },
            {
                "p": "colors",
                "v": "[\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\",\"#ffa916\"]",
                "vt": "json"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "-10",
        "payloadType": "num",
        "x": 570,
        "y": 780,
        "wires": [
            [
                "ca976be470bdfe6c"
            ]
        ]
    },
    {
        "id": "c82ecbea129ea0dc",
        "type": "ui-group",
        "name": "Input Names",
        "page": "17cb6bf25674552b",
        "width": "11",
        "height": "1",
        "order": 4,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "17cb6bf25674552b",
        "type": "ui-page",
        "name": "Real Auto Tricaster",
        "ui": "e51c8ddc14062d86",
        "path": "/TCautoreal",
        "icon": "home",
        "layout": "grid",
        "theme": "0d92c765bfad87e6",
        "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": 5,
        "className": "",
        "visible": true,
        "disabled": false
    },
    {
        "id": "e51c8ddc14062d86",
        "type": "ui-base",
        "name": "My Dashboard",
        "path": "/dashboard",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-notification",
            "ui-control"
        ],
        "showPathInSidebar": false,
        "headerContent": "page",
        "navigationStyle": "default",
        "titleBarStyle": "default",
        "notificationDisplayTime": 5
    },
    {
        "id": "0d92c765bfad87e6",
        "type": "ui-theme",
        "name": "Basic Blue Theme",
        "colors": {
            "surface": "#4d58ff",
            "primary": "#0094ce",
            "bgPage": "#eeeeee",
            "groupBg": "#ffffff",
            "groupOutline": "#cccccc"
        },
        "sizes": {
            "pagePadding": "12px",
            "groupGap": "12px",
            "groupBorderRadius": "4px",
            "widgetGap": "12px"
        }
    }
]

Thanks !

But why with template....

Wooh , I missed that one !!

You did it again ! I'll check that and let you know. Might take time as I'm working on a affline computer.

Thank you very much and have a good day

Hi, I was that close to get you a bunch of coffees, I did a quick test and it seems that could do the job.
However the thing is I want to use it in a subflow, and there is no possibility to set the size of the node in the layout, it defaults to auto, and the fields to set the size manually for nodes in subflows are not available..... so :

(and as you can see I have same problem with LED, which I will replace with a template. )

So in the end , do you think there is possibility to adapt the node to make it compatible with subflows ?
Or if too complicated, I could still work with the meter in template, I just miss the way to tweak the colors dynamically.

Thanks !

I think I'v seen a bit of code for widgets to support subflow sizing, it is definitely missing from this node. I can check maybe later today.

Excellent ! Much appreciated

V 0.1.10 available.

1 Like

You're the one !!

Thank you very much, now I go to bring you some coffees !

Cheers

1 Like