Yes, it is entirely possible to embed Vega Lite – like any Javascript library – into an Anvil app. You have to write a little bit of Javascript to glue it together, but once that’s done you can use it entirely from Python. Here’s an example app, and a step-by-step guide to how I built it.
Here’s the example app, which embeds the example you just linked to:
https://anvil.works/build#clone:EBK7KDYPKS7V4ADB=YQK2LLDCPHBOZAITZIB3BWS6
And here’s how I did it:
1. Import the Vega embedding libraries
I found the documentation on the Vega Lite website about embedding Vega Lite visualisations into a web app, and I found out what HTML snippet it wanted me to add to my app. I copied-and-pasted these into the Native Libraries section of my app:
<script src="https://cdn.jsdelivr.net/npm/vega@4.4.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@3.0.0-rc12"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@3.29.1"></script>
2. Initialise Vega with Javascript
The website also provided sample Javascript code for setting up a visualisation in a particular HTML element. I made a new Custom HTML form, and I put this code into a function in a <script>
tag, so I could call it from Python.
Here’s the whole Custom HTML from the VegaLite
form:
<div class="vis"></div>
<script>
function initVegaLite(spec) {
var visElt = $(this).find(".vis")[0];
vegaEmbed(visElt, spec);
}
</script>
3. Make a Python custom component
I set up my new form as a Custom Component, and gave it a property called vl_spec
(type “object”, because it’ll want complex nested dictionaries/lists/etc). I then wrote the Python @property
getter and setter to store that property, and call the initVegaLite()
Javascript function when the form is shown or when the property is updated.
Here’s the full code for that form:
class VegaLite(VegaLiteTemplate):
def __init__(self, **properties):
self._vl_spec = {}
self._shown = False
self.init_components(**properties)
@property
def vl_spec(self):
return self._vl_spec
@vl_spec.setter
def vl_spec(self, new_val):
self._vl_spec = new_val
if self._shown:
self.call_js('initVegaLite', self._vl_spec)
def form_show(self, **event_args):
self._shown = True
# Fire the setter again to call the init function
self.vl_spec = self._vl_spec
4. Use the component
Now I’ve created a Custom Component, the VegaLite
form is in my Toolbox, ready to use from my other forms. I drop one onto Form1
, and then set up its vl_spec
from Form1’s __init__
function:
self.vega_lite_1.vl_spec = {...}
(The example vl_spec
is copied from the example @jim linked to, although I had to change the data URL from "data/movies.json"
to "https://vega.github.io/vega-datasets/data/movies.json"
)
And there we have it – now you have a component you can use to put any Vega Lite visualisation into an Anvil app. And now we’ve built it, you don’t have to touch the Javascript again – you can do it all from Python!