Folium Component (bi-directional communication)(WIP)

Hello :wave:

What kind of bi-directional communication would you use with Folium? (I’m not a Folium user)

However if you want to embed Folium maps statically, st.html() does the work:

import folium
import streamlit as st

MAP_HEIGHT = 500

st.title("Folium showcase")

fig = folium.Figure(height=MAP_HEIGHT)
fig.add_child(folium.Map(location=[45.5236, -122.6750]))

st.html(fig._repr_html_(), height=MAP_HEIGHT+10)

Here’s an explanation on why we need to use folium.Figure(), what is _repr_html_() and why we need to add +10 to st.html()'s height.

Let’s take the first example from Folium’s quickstart guide:

import folium

m = folium.Map(location=[45.5236, -122.6750])
m

Jupyter notebooks display these widgets thanks to _repr_html_(), and Folium’s Map class implements it as expected.

By the way, maybe we could add a new st.ipywidget() or st.plot() to automatically call _repr_*_() functions, which would make streamlit support jupyter’s widgets natively.

That said, let’s try getting the html code of our map and pass it to st.html():

import folium
import streamlit as st

m = folium.Map(location=[45.5236, -122.6750])
st.html(m._repr_html_())

.

It works, but there’s a height issue. We could fix this by passing a height argument to st.html() according to the map’s default height, but it is set as 100%. So we must fix the map’s height ourselves.

I found out that folium.Map() takes a height parameter, but it doesn’t work neither. When you call folium.Map(), internally it creates a folium.Figure() with a height of 100% which will contain the map.

The solution to control the height is to create a folium.Figure() ourselves with the height we want, and then add our map to it.

import folium
import streamlit as st

f = folium.Figure(height=500)
m = folium.Map(location=[45.5236, -122.6750])
f.add_child(m)

st.html(f._repr_html_(), height=500)


It works, but for some reason it’s cropped down there. Actually, I had this glitch when implementing other custom components. I don’t know what causes it yet, but for now to bypass this, I just added +10 to the height of st.html().