Custom gauge with adjustable properties

Hi all,

I’m sharing this gauge which I have adapted to be easily used within Anvil as a custom component and has some adjustable properties.

Credit to these 2 links which I used:

https://ifpb.github.io/javascript-guide/packages/chart/gaugejs/

It works as long as you only use 1 gauge within your form.

If someone could assist me with changing the relevant bits of code such that we can use multiple gauges on the same form, that would be great then more people can use it. The current issue I’m having is that when a second gauge is added to the page, the identifier which I used “target” already exists. To replicate the issue, just drag a second gauge on the main form and run the app, you’ll quickly see the issue but I don’t yet know how to overcome it.

2 Likes

Hi Neeeco,

I experienced the same problem, with having multiple instances of the custom html component.

From what I understand, the problem/conflict appears because the gauge Class Name or ID is hardcoded. When having multiple instances of the html components, all gauges will have the same style/behaviour because Class name or ID is identical.
I hope this make sense :slight_smile:

Maybe someone from the anvil team have an idea how to solve the above.

If I were you I would not use the custom html component and instead create the gauge directly in the python code (form load).
This can be achieved using anvil.js and anvil.js.window where you can e.g. just drag and drop a spacer on to the form and via python code, replace the spacer content with your Gauge object. In this scenario you can have multiple instances.

Please see the above example. I hope you find it useful :slight_smile:

@Neeeco good work on the gauge component!


Multiple gauge components

One option to fix this issue is to pass the dom node to the javascript initGauge function.
(the one you’re calling in the form show handler)

instead of using document query selectors to get the target,
your initGauge method might look like

  function initGauge(target) {
    // rest of method
  }

And you’d call it form python like:

def form_show(self, **event_args):
    ...
    self.call_js('initGauge', anvil.js.get_dom_node(self).querySelector("canvas"))

(Adjusting your javascript setHeight accordingly)

You’ll probably need to add arguments for the other attributes too. Rather than using the scoped values like initMinValue.

I’d then consider moving this query selector to the init method like:

def __init__(self, **props):
    ...
    self.canvas_node = anvil.js.get_dom_node(self).querySelector("canvas")

def form_show(self, **event_args):
    ...
    self.call_js("initGauge", self.canvas_node)

(side note - an anvil canvas also works for this component rather than needing to include one in the html)

Script tags

I’d consider moving this script tag into native libraries

 <script src="https://cdnjs.cloudflare.com/ajax/libs/gauge.js/1.3.5/gauge.min.js"></script>

You’ll be loading this script tag for each custom gauge you have on the screen, which is probably not what you want.

Using JavaScript in Python

Something else to consider is that you could move all your javascript code to python
A simple example might be the height

from anvil.js.window import jQuery as _S


...
  @height.setter
  def height(self, h):
    self._height = h
    _S(self.canvas).css("height", h)

But you could do this with all the javascript if you wanted.

Property changes

The way you’ve written the code means you’re creating a new javascript Gauge object on each change of property.

Addressing this for the value property will fix the animation of the gauge as the value changes.
i.e. it will animate from one value to the next, rather than redrawing it and animating from the minimum value

2 Likes

Thanks @stucork and @tobias.carlbom for pointing me in the right direction!

So I’ve made many changes and it’s working much better now. Here is an updated link.
Gauge

I’ll be improving it on the side and adding more adjustable properties with time. But for now it should be a handy extra for those interested in using it.

4 Likes