# Gauge's for Dashboard 2.0 made with ui\_template

**URL:** <https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [27 February 2024 13:43 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955 "2024-02-27T13:43:09Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [8 March 2024 12:34 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/61 "2024-03-08T12:34:02Z")

</div>

There are a few ways, but based on how the above example is setup, you could add to the watch:

```auto
 watch: {
        msg: function(){    
            if(this.msg.payload !== undefined){  
                const v = this.validate(this.msg.payload)                
                if(v === null){
                    return
                }         
                this.value = v
                this.changeLine()              
            }
            if(this.msg.icon) {
                this.icon = icon
            }
        }
    },

```

then just include an `icon` property set to `"mdi-something"` in the `msg` you send to the template.

---

<div class="post-metadata">

**Author:** ![Giamma](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Giamma](https://discourse.nodered.org/u/Giamma)\
**Post date:** [8 March 2024 13:01 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/62 "2024-03-08T13:01:22Z")

</div>

Hi,  
I try to work with wind compass in Dashboard 2.0 and I would like  
to set the color speed text according the wind speed (this.speed).  
Is possible to set the color text in style with a variable set in the script?

![xxx](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/5/95df9db8152727ad4eb46db3468d64f8f2f21226.png)

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [8 March 2024 13:21 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/63 "2024-03-08T13:21:32Z")

</div>

Yes.

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/1/f1896daef1a03434aba5289b9cf91f094f093aff.png)  
.

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/a/4ace02e0336689b7ccf8faccada6b14062323852.png)

Where red line is, make your logic as you wish.

---

<div class="post-metadata">

**Author:** ![vapourlyric](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@vapourlyric](https://discourse.nodered.org/u/vapourlyric)\
**Post date:** [8 March 2024 13:50 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/64 "2024-03-08T13:50:08Z")

</div>

@Steve-Mcl Thanks for your hint. This is the watch method that I am now using:

```auto
    watch: {
        msg: function(){    
            if(this.msg.payload !== undefined){  
                const v = this.validate(this.msg.payload)                
                if(v === null){
                    return
                }         
                this.value = v
                if(this.type != "artless"){
                    this.lit()
                }
                else{
                    this.changeLine()
                }
            }
            if(this.msg.icon) {
                this.icon = this.msg.icon
            }
        }
    },

```

Can anybody give me a hint regarding the icon colour?

---

<div class="post-metadata">

**Author:** ![Giamma](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Giamma](https://discourse.nodered.org/u/Giamma)\
**Post date:** [8 March 2024 13:54 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/65 "2024-03-08T13:54:50Z")

</div>

Thank you very much .....

![gggg](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/9/c94fba154e53c1837e8f5350a4af35b1f09408a9.png)

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [8 March 2024 13:56 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/66 "2024-03-08T13:56:01Z")

</div>

> [@vapourlyric](#):
>
> Can anybody give me a hint regarding the icon colour?

Look at the post one above yours.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [8 March 2024 15:21 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/67 "2024-03-08T15:21:12Z")

</div>

@Colin@arturv2000  
Made another try to make the scale divisions configurable. See if that does the trick for you.

> **Code is HERE**
>
> ```auto
> <template>
> <div class="hn-sng">
> <div class="label">{{label}}</div>
> <svg ref="hn-gauge" width="100%" height="100%" viewBox="0 0 100 100">
> <g>
> <path v-for="(item, index) in sectors" :key="index" :ref="'sector-' + index" class="sector"
> stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90"></path>
> </g>
> <g>
> <path class="tick-minor" :style="{'stroke-dasharray':minor }" pathLength="496" stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90" ></path>
> <path ref="arc" class="tick-major" :style="{'stroke-dasharray':major }" pathLength="248" stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90"></path>
> </g>
> <g>
> <text v-for="(item, index) in numbers" :key="index" class="num" text-anchor="middle" y="-37"
> :style="`rotate: ${item.r}deg;`">{{item.n}}</text>
> </g>
> <g>
> <text class="measurement" y="48" x="50%" text-anchor="middle">{{measurement}}</text>
> <text class="unit" y="75" x="50%" text-anchor="middle">{{unit}}</text>
> <text class="value" y="90" x="50%" text-anchor="middle">{{formattedValue}}</text>
> <text v-if="showUpdate" ref="update" class="update" y="100" x="0"
> text-anchor="left">{{formattedUpdate}}</text>
> </g>
> <g ref="o-needle" class="o-needle">
> <path d="M 0,0 -1.5,0 -0.15,-40 0.15,-40 1.5,0 z"></path>
> <circle cx="0" cy="0" r="3"></circle>
> </g>
> </svg>
> </div>
> </template>
> <script>
> export default{
> data(){
> return {
> //define me here
> min:-50,
> max:50,
> unit:"kg",
> label:"Yet another gauge",
> measurement:"Plums",
> updateLabel:"Last update:",
> divisors:{major:10,minor:10},
> sectors:[{start:-50,end:0,color:"#63cc25"},{start:10,end:20,color:"orange"},{start:20,end:50,color:"red"}],
> showUpdate:true,
>                 
> //no need to change
> value:0,
> updateTime:0                             
> }
> },
> methods:{
> getElement: function(name,base){
> if(base){
> return this.$refs[name]
> }
> return this.$refs[name][0]
> },
> validate: function(data){
> let ret                
> if(typeof data !== "number"){
> ret = parseFloat(data)
> if(isNaN(ret)){
> console.log("BAD DATA! gauge id:",this.id,"data:",data)
> return null
> }
> }                    
> else{
> ret = data
> }                
> return ret
> },
> range:function (n, p, r) {           
> if (n < p.minIn) {
> n=p.minIn;
> }
> if (n > p.maxIn) {
> n = p.maxIn;
> }
> if(r){
> return Math.round(((n - p.minIn) / (p.maxIn - p.minIn) * (p.maxOut - p.minOut)) + p.minOut);
> }
> return ((n - p.minIn) / (p.maxIn - p.minIn) * (p.maxOut - p.minOut)) + p.minOut;
> },
> generateNumbers:function(min,max){               
>                
> let nums = []
> let t = (max - min) / this.divisors.major;
> let i = min;
> let ro = -123
> let rp = 246 / this.divisors.major
>                
> for (let e = 0; e < this.divisors.major + 1; ++e){
> nums.push({n: i,r: ro + (e * rp) })
> i = parseFloat((i + t).toFixed(2));                   
> }
> return nums 
> },
> sectorData:function(full){               
> let params, pos, span, sec, str
> let ret = [] 
> this.sectors.forEach((sector,idx) => {
> sec = {name:'sector-'+idx,color:sector.color}
> params = {minIn:this.min, maxIn:this.max, minOut:0, maxOut:full}                   
> pos = this.range(sector.start,params,false)
> params = {minIn:0, maxIn:this.max-this.min, minOut:0, maxOut:full}
> span = this.range(sector.end - sector.start,params,false)                    
> sec.css = "0 "+pos+" "+span+" var(--dash)"
> ret.push(sec)
> })
> return ret
> },
> rotation:function(v){
> const params = {minIn:this.min, maxIn:this.max, minOut:-123, maxOut:123};
> return this.range(v,params,false) +'deg'          
> }
> 
> },
> watch: {
> msg: function(){
> if(this.msg.payload != undefined){                   
> const v = this.validate(this.msg.payload)                   
> if(v == null){
> return
> }
> this.value = v
> this.updateTime = Date.now()                    
> this.getElement('o-needle',true).style.rotate = this.rotation(this.value)                    
> }
> }
> },
> computed: {
> formattedValue: function () {
> return this.value.toFixed(1)
> },
> formattedUpdate:function (){
> return this.updateLabel+" "+this.time
> },
> time:function(){
> return new Intl.DateTimeFormat('default', {hour: 'numeric', minute: 'numeric',second: 'numeric'}).format(this.updateTime);
> },
> numbers:function(){
> return this.generateNumbers(this.min,this.max)
> },
> major:function(){
> return "1," + ((246 / this.divisors.major) - 1)           
> },
> minor:function(){
> let step = 492 / this.divisors.major / this.divisors.minor
> let line = "0," + step + ","
> step --
> for(let i=0;i<this.divisors.minor-1;++i){
> line += "1,"+step+","
> }
> line = line.slice(0, -1);
> 
> return line
> },
> offset:function(){
> return -1
> }
> 
> },
> mounted(){
>            
> const dal = this.getElement('arc',true).getTotalLength()
> const sec = this.sectorData(dal)              
> const gauge = this.getElement('hn-gauge',true)
> gauge.style.setProperty('--dash',dal)
>            
> sec.forEach(s =>{
> const sector = this.getElement(s.name,false)
> sector.style.setProperty("stroke-dasharray",s.css)
> sector.style.setProperty("stroke",s.color)
> })            
> 
> }
> 
> }
> </script>
> <style>
> .hn-sng {
> position: relative;
> }
> 
> .hn-sng .label {
> position: absolute;
> font-size: 1rem;
> color: currentColor;
> text-align: center;
> width: 100%;
> overflow: hidden;
> white-space: nowrap;
> text-overflow: ellipsis;
> }
> 
> .hn-sng .value {
> fill: currentColor;
> font-weigth: 600;
> }
> 
> .hn-sng .unit {
> fill: currentColor;
> font-size: 0.4rem;
> }
> 
> .hn-sng .measurement {
> fill: currentColor;
> font-size: 0.5rem;
> }
> 
> .hn-sng .update {
> fill: currentColor;
> fill-opacity: 0.6;
> font-size: 0.35rem;
> }
> 
> .hn-sng .num {
> transform-origin: center 64%;
> transform: translate(50%, 64%);
> fill: currentColor;
> fill-opacity: 0.6;
> font-size: .35rem;
> }
> 
> .hn-sng .tick-minor {       
> stroke-dashoffset: -2;
> fill: none;
> stroke: currentColor;
> stroke-opacity: 0.6;
> }
> 
> .hn-sng .tick-major {
> stroke-dashoffset: -1;
> fill: none;
> stroke: currentColor;
> }
> 
> .hn-sng .sector {
> fill: none;
> stroke: transparent;
> }
> .hn-sng .sector:first-of-type {
> stroke-dashoffset:-0.5;
> }
> 
> .hn-sng .o-needle {
> transform-origin: center 64%;
> transform: translate(50%, 64%);
> transition: rotate .5s;
> }
> 
> .hn-sng .o-needle path,
> .hn-sng .o-needle circle {
> fill: currentColor;
> }
> </style>
> 
> ```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/2/f2c187a8e90e26a026834d71dcae53cc3d127480.png)

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [8 March 2024 19:27 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/68 "2024-03-08T19:27:41Z")

</div>

> [@hotNipi](#):
>
> Made another try to make the scale divisions configurable

Liking the 'last update' time addition, that's really useful to ensure that data is not stale.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [8 March 2024 19:32 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/69 "2024-03-08T19:32:30Z")

</div>

Just it is time of last msg which can be also replay when you open the dashboard so it isn't absolute check for equipment or communication quality.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [8 March 2024 19:37 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/70 "2024-03-08T19:37:34Z")

</div>

> [@hotNipi](#):
>
> which can be also replay when you open the dashboard

Yes, I've just spotted that, but it's OK for data that is frequently updated.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [8 March 2024 19:45 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/71 "2024-03-08T19:45:06Z")

</div>

But nothing prevents you to send that last update as property of msg.payload and then it indicates more actual thing. Just some slight changes needed about what the payload structure should be and stuff around it.

---

<div class="post-metadata">

**Author:** ![Giamma](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Giamma](https://discourse.nodered.org/u/Giamma)\
**Post date:** [9 March 2024 10:07 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/72 "2024-03-09T10:07:00Z")

</div>

@hotNipi  
be patient, but dashboard 2 is very difficult for me ...  
I would like to set one vertical gauge for humidity value ...  
I copied your code but I have only this component ....

 ![kkkkk](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/c/ac1ff5bee2a80d4e3d0c36b353f81532a4744792.png)

What should I do to show the vertical gauge?

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [9 March 2024 11:02 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/73 "2024-03-09T11:02:57Z")

</div>

Post nr 3 in this thread shows configuration options.  
That is if you copied stuff from first post.

---

<div class="post-metadata">

**Author:** ![Giamma](https://avatars.discourse-cdn.com/v4/letter/g/e47774/32.png) [@Giamma](https://discourse.nodered.org/u/Giamma)\
**Post date:** [9 March 2024 11:58 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/74 "2024-03-09T11:58:47Z")

</div>

Found!  
Thank you again ...(I will not disturb you anymore)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [9 March 2024 12:01 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/75 "2024-03-09T12:01:32Z")

</div>

Meanwhile I have made some further mods

1. Allowed scale min to be greater than scale max

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/3/73feb61610dbf558f891a09e33c3608bf3208224.png)

1. When an invalid payload is received, instead of ignoring it, show `---` and put the needle off the end. I like this because you can add a trigger node before it that sends an invalid message if the inputs stop coming in so it is obvious if the inputs fail. Also this display is the default before any messages are received.

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/4/d48fbc82851c3a1e054e8b7e203dc5b29da4432a.png)

@hotNipi would you like me to merge either or both of these into your version?

> **Click here to see code**
>
> ```auto
> <!-- Gauge Template CDL v1.2  
> Based on original work by @HotNipi 
> -->
> <template>
> <div class="hn-sng">
> <div class="label">{{label}}</div>
> <svg ref="hn-gauge" width="100%" height="100%" viewBox="0 0 100 100">
> <g>
> <path v-for="(item, index) in sectors" :key="index" :ref="'sector-' + index" class="sector" stroke-width="5" d="M 10 90 A 47.5 47.5 25 1 1 90 90"></path>                
> </g>
> <g>
> <path class="tick-minor" stroke-width="5" d="M 10 90 A 47.5 47.5 0 1 1 90 90" :style="tickStyle(this.minorDivision, 0.5)"></path>
> <path ref="arc" class="tick-major" stroke-width="5" d="M 10 90 A 47.5 47.5 0 1 1 90 90" :style="tickStyle(this.majorDivision, 2)"></path>
>                 
> </g>         
> <g>
> <text v-for="(item, index) in numbers" :key="index" class="num" text-anchor="middle" y="-37" :style="`rotate: ${item.r}deg;`">{{item.n}}</text>
> </g>
> <g>
> <text class="measurement" y="48" x="50%" text-anchor="middle">{{measurement}}</text>
> <text class="unit" y="75" x="50%" text-anchor="middle">{{unit}}</text>
> <text class="value" y="90" x="50%" text-anchor="middle">{{formattedValue}}</text>
> </g>
> <g ref="o-needle" class="o-needle">
> <path d="M 0,0 -1.5,0 -0.15,-43 0.15,-43 1.5,0 z"></path>
> <circle cx="0" cy="0" r="3"></circle>
> </g>
> </svg>
> </div>
> </template>
> <script>
> export default{
> data(){
> return {
> //define settings here
> // Min and max scale values. Max may be less that min.
> min:0,
> max:1.4,
> //min:0,
> //max:-1.4,
> majorDivision: 0.2, // number of input units for each (numbered) major division
> minorDivision: 0.05, // number of input units for each minor division
> unit:"°C",
> label:"Hot Water",
> measurement:"Temperature",
> valueDecimalPlaces: 2, // number of decimal places to show in the value display
> majorDecimalPlaces: 1, // number of decimal places to show on the scale
> // Coloured sectors around the scale. Sectors can be in any order and it makes no difference if 
> // start and end are reversed.
> // Any gaps are left at background colour
> sectors:[{start:0,end:0.4,color:"skyblue"},{start:0.4,end:0.75,color:"green"},{start:0.75,end:1.4,color:"red"}],
> //sectors:[{start:0,end:-0.4,color:"skyblue"},{start:-0.4,end:-0.75,color:"green"},{start:-0.75,end:-1.4,color:"red"}],
>                 
> //no need to change
> value: null
> }
> },
> methods:{
> getElement: function(name,base){
> if(base){
> return this.$refs[name]
> }
> return this.$refs[name][0]
> },
> validate: function(data){
> let ret                
> if(typeof data !== "number"){
> ret = parseFloat(data)
> if(isNaN(ret)){
> console.log("BAD DATA! gauge id:",this.id,"data:",data)
> ret = null
> }
> }                    
> else{
> ret = data
> }                
> return ret
> },
> range:function (n, p, r) {
> // clamp n to be within input range
> if (p.maxIn > p.minIn) {
> n = Math.min(n, p.maxIn)
> n = Math.max(n, p.minIn)
> } else {
> n = Math.min(n, p.minIn)
> n = Math.max(n, p.maxIn)
> }
> if(r){
> return Math.round(((n - p.minIn) / (p.maxIn - p.minIn) * (p.maxOut - p.minOut)) + p.minOut);
> }
> return ((n - p.minIn) / (p.maxIn - p.minIn) * (p.maxOut - p.minOut)) + p.minOut;
> },
> generateNumbers:function(min,max,majorDivision){    
> let minDegrees, maxDegrees, startValue
> if (max > min) {
> minDegrees = 237.36
> maxDegrees = 482.64
> startValue = min    
> } else {
> minDegrees = 482.64
> maxDegrees = 237.36
> startValue = max              
> }
> // Calculate number of major divisions, adding on a bit and rounding down in case last one is just off the end
> const numDivs = Math.floor(Math.abs(max-min) / majorDivision + 0.1)
> const degRange = maxDegrees-minDegrees
> const degPerDiv = degRange * majorDivision/Math.abs(max-min)
> let nums = []
> for (let div=0; div<=numDivs; div++) {
> let degrees = div*degPerDiv + minDegrees
> const n = (startValue + div * majorDivision).toFixed(this.majorDecimalPlaces)
> nums.push({r: degrees, n: n})
> }
> return nums 
> },
> sectorData:function(full){               
> let ret = []
> this.sectors.forEach((sector,idx) => {
> let sec = {name:'sector-'+idx,color:sector.color}
> const params = {minIn:this.min, maxIn:this.max, minOut:0, maxOut:full}
> const start = this.range(sector.start,params,false)
> const end = this.range(sector.end,params,false)
> const pos = Math.min(start, end)
> const span = Math.max(start, end) - pos
> sec.css = `0 ${pos} ${span} var(--dash)`
> ret.push(sec)
> console.log(`sec: ${JSON.stringify(sec)}`)
> })
> return ret
> },
> rotation:function(v){
> // allow pointer to go 10% off ends of scale
> const overflow = (this.max-this.min)*0.1
> const maxAngle = 122.64 * 1.2 // 1.2 as this is only half the range, so need 20%
> const min = this.min - overflow
> const max = this.max + overflow
> const params = {minIn:min, maxIn:max, minOut:-maxAngle, maxOut:maxAngle};
> if (v === null) {
> v = Math.min(min, max)
> }
> return `${this.range(v,params,false)}deg`
> },
> tickStyle: function(division, width) {
> // division is the number of input units per tick
> // width is the width (length?) of the tick in svg units
> 
> // total arc length in svg units
> const arcLength = 203.356
> // length in user units
> const range = Math.abs(this.max - this.min)
> const tickPeriod = division/range * arcLength
> // marker is width wide, so gap is tickPeriod-width
> // stroke-dashoffset sets the first tick to half width
> return `stroke-dasharray: ${width} ${tickPeriod-width}; stroke-dashoffset: ${width/2};`
> },
> },
> watch: {
> msg: function(){
> // allow undefined payload through as it will show the invalid data state
> const v = this.validate(this.msg.payload)                   
> // v is null if payload is invalid, this is coped with then it is displayed
> this.value = v
> this.getElement('o-needle',true).style.rotate = this.rotation(this.value)    
> }
> },
> computed: {
> formattedValue: function () {
> // Show --- for the value until a valid value is recevied
> return this.value !== null ? this.value.toFixed(this.valueDecimalPlaces) : "---"
> },
> numbers:function(){
> return this.generateNumbers(this.min,this.max,this.majorDivision)
> },
> },
> mounted(){
>            
> const dal = this.getElement('arc',true).getTotalLength()
> const sec = this.sectorData(dal)              
> const gauge = this.getElement('hn-gauge',true)
> gauge.style.setProperty('--dash',dal)
> sec.forEach(s =>{
> const sector = this.getElement(s.name,false)
> sector.style.setProperty("stroke-dasharray",s.css)
> sector.style.setProperty("stroke",s.color)
> })
> // initialise the needle off the bottom
> this.getElement('o-needle',true).style.rotate = this.rotation(null) 
> }
> 
> }
> </script>
> <style>
> .hn-sng{
> position:relative;
> }
> .hn-sng .label{
> position:absolute;
> font-size:1rem;
> color:currentColor;
> text-align:center;
> width:100%;
> overflow: hidden;
> white-space: nowrap;
> text-overflow: ellipsis;
> }
> .hn-sng .value {
> fill:currentColor;
> }
> .hn-sng .unit {
> fill:currentColor;
> font-size:0.4rem;
> }
> .hn-sng .measurement {
> fill:currentColor;
> font-size:0.5rem;
> }
> .hn-sng .num{
> transform-origin: center 64%;
> transform: translate(50%, 64%);
> fill:currentColor;
> fill-opacity:0.6;
> font-size:.35rem;
> }
> .hn-sng .tick-minor{
> fill:none;
> stroke:currentColor;
> stroke-opacity:0.6;
> }
> .hn-sng .tick-major{
> fill:none;
> stroke:currentColor;
> }
> .hn-sng .sector{        
> fill:none;
> stroke:transparent;      
> }    
> .hn-sng .o-needle{        
> transform-origin: center 64%;
> transform: translate(50%, 64%);
> transition:.5s;
> }    
> .hn-sng .o-needle path, .hn-sng .o-needle circle{
> fill:red;
> }
>     
> </style>
> 
> ```

Edit: Somehow I lost the hub from the needle. I have put it back in now.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [9 March 2024 12:50 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/76 "2024-03-09T12:50:08Z")

</div>

I'll do. Just not right now. Too much spring 🌼🌱 knocks to come in.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [9 March 2024 13:36 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/77 "2024-03-09T13:36:13Z")

</div>

> [@hotNipi](#):
>
> Too much spring 🌼🌱 knocks to come in.

You are right there, much to do outside.

> [@hotNipi](#):
>
> Made another try to make the scale divisions configurable

I can't say that I am very keen on that method. To me it seems more user friendly to specify the divisions in the user's units rather than how many divisions there should be along the arc.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [9 March 2024 14:08 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/78 "2024-03-09T14:08:50Z")

</div>

Ask the arbitrary user about the user units. Therm is unknown thus I can't see the value.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [9 March 2024 16:27 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/79 "2024-03-09T16:27:44Z")

</div>

> [@hotNipi](#):
>
> Ask the arbitrary user about the user units.

I don't think I know any ☹

> [@hotNipi](#):
>
> Therm is unknown thus I can't see the value.

Sorry, I don't understand.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [9 March 2024 16:41 UTC](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955/80 "2024-03-09T16:41:10Z")

</div>

On a side note I have discovered that one can split the export script into two sections so one can have in the ui-template

```auto
<script>
    export default{
        data(){
            return {
                //define settings here
                // Min and max scale values. Max may be less that min.
                min:0,
                max:1.4,
                ...
            }
        },
    }      
</script>

<template>
    all the template stuff
</template>    

<script>
    export default{
      methods, computed, watch etc
    }
</script>

```

Which I think makes it easier to configure, as all the config is at the start.

[Previous page](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955.md?page=3)

[Next page](https://discourse.nodered.org/t/gauges-for-dashboard-2-0-made-with-ui-template/85955.md?page=5)
