st_folium: Creating link in the popup that redirects to another page within the streamlit dashboard

Good morning!

I’m building a Streamlit dashboard that shows the amount of subsidence we measure for our customer. To visualize our data, we provide multiple visualizations on multiple pages across the Streamlit application. Our current optimalization is to link between the visualizations with the use of URL parameters (i.e: my-streamlit.com/vis1&pointid=98, my-streamlit.com/vis2&pointid=98 etc.)

One of the visualizations is a GIS-map build on the Folium package. With the use of a html-builder function (that uses a GeoDataFrame as input) I’ve managed to create a button-like link (using the HTML tag) that builds the correct redirect link to one of our visualizations. Since we use the st.session_state function to store our build-in authorization, the user cannot open a new tab or refresh the Streamlit application. Therefore, the “target” parameter is set to “_parent” since the folium map is render as an iframe (using the st_folium package)

But when i click on the link, i got an error (in the browser console):

image

The code:

def _link_builder(

        self, # This function is part of a Map builder class

        feature: pd.Series,

        base_url: str,

        params: Optional[dict[str, str]] = None,

        link_text: str = 'Link',

        style: str | Literal['default'] = 'default',

    ) -> str:

        """

        Builds a HTML link element (with URL parameters) using the `<a>` tag and the input features data.

        Use the `df.apply()` (or `gdf.apply()`) function with the lamdba syntax to generate the HTML elements.




        Parameters

        ----------

        feature: pd.Series

            A feature using the `df.apply` (or `gdf.apply()`) function




        base_url: str

            The base URL of the link




        params: dict[str, str], optional

            A dictionary with the URL parameters and the corresponding column names in the `feature` object




        link_text: str, default = "Link"

            The text that will be shown in the link




        style: str or "default", default = "default"

            CSS-like string that styles the link element.

            If "default" is given, the `_default_link_style` property will be applied




        Returns

        -------

        str

            HTML link element that can be used in the `folium.GeoJsonPopup` or `folium.GeoJsonTooltip` functions




        Example

        -------

        >>> # This will create a new column 'link' in the DataFrame with HTML link elements for each row

        >>> df['link'] = df.apply(lambda feature: self._link_builder(feature, base_url="https://www.example.com", params={"id": "id_col"}, link_text="Click here"), axis=1)

        >>> df['link']

        >>> 0    <a href="
" target="_blank">Click here</a>

        >>> 1    <a href="
" target="_blank">Click here</a>

        >>> ...

        """

        # Create the base <a> tag. Target is set to parent since folium maps are renderd within an IFrame

        html_element = f"<a target = '_parent' href ={base_url}"




        if params is not None:

            html_element += '?'

            # Create the URL parameters path

            url_params = []

            for k, v in params.items():

                url_params.append(

                    f'{k}={feature[v]}'

                )  # Key = URL parameter name. Value = Feature propery column

            html_element += '&'.join(url_params)




        # Apply the CSS style parameter

        html_element += (

            f' style = {self._default_link_style if style == "default" else style}'

        )




        # Add the text and return the HTML element

        html_element += f'>{link_text}</a>'

        return html_element

Results in the following HTML:

<a target = '_parent' href =https://www.example.com?id=1307 style =
color: #FAFAFA;
background-color: #78c864;
border-radius: 10px;
text-decoration: none;
font-weight: bold;
>Link</a>

Does anyone have a solution or a workaround on the issue?