Embedded interactive visualisations in Anvil using e.g. Vega Lite?

@jim In addition to Meredydd’s solution, I’ve been using Vega-Lite via its Python API Altair.

With this approach, I can write the code for the chart using Python instead of JSON. Altair produces the corresponding JSON needed for Vega-Lite. The JSON is plugged into some html, and the html is displayed in an iframe.

Client code

    media=anvil.server.call('make_chart')
    self.i_frame_1.url=media.get_url(True)

Server code

make chart with Altair

    @anvil.server.callable
    def make_chart():
      
        source = pd.DataFrame({
            'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
            'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
        })
        
        c=alt.Chart(source).mark_bar().encode(
            x='a',
            y='b'
        )

grab the JSON and stick it into some html

        altair_spec = c.to_json().replace('\n', '')

        html = """
        <!DOCTYPE html>
        <html>
        <head>

        <script src="https://cdn.jsdelivr.net/npm/vega@4"></script>
        <script src="https://cdn.jsdelivr.net/npm/vega-lite@3.0.0-rc8"></script>
        <script src="https://cdn.jsdelivr.net/npm/vega-embed@3"></script>

        </head>
        <body>
          <div id="vis"></div>
          <script type="text/javascript">
            var spec = {json_spec};
            var embed_opt = {{"mode": "vega-lite", "renderer": "svg"}};

            function showError(el, error){{
                el.innerHTML = ('<div class="error">'
                                + '<p>JavaScript Error: ' + error.message + '</p>'
                                + "<p>This usually means there's a typo in your chart specification. "
                                + "See the javascript console for the full traceback.</p>"
                                + '</div>');
                throw error;
            }}
            const el = document.getElementById('vis');
            vegaEmbed("#vis", spec, embed_opt)
              .catch(error => showError(el, error));
          </script>
        </body>
        </html>
        """.format(json_spec=altair_spec)

return the html as media

        media = anvil.BlobMedia(content_type='text/html', content=html)
        
        return media

An example app (note that you will need the iframe component)

https://anvil.works/build#clone:EKTF2GOLLOTSWKOS=ZIHI6PZRUKESB6GVB4GYV6OJ

1 Like