Add annotation to chart directly in Streamlit

Hi,

My streamlit app generates charts using Plotly.

Plotly allows you to add annotations to a chart, for instance under the chart title like so.

image

But the annotation is hard coded.

user_input="This is my hard-coded annotathon that helps understand the chart and that I would like to type in with a widget."
fig.add_annotation(text = user_input,
                   xref = "paper",
                   yref = "paper",
                   x = 0,
                   y = 1.060,
                   showarrow = False,
                   align = "left",
                   xanchor = "left",
                   font = dict(size = 11, color = "#242526"))

I would like the user to be able write the annotation into a text input widget and (after re-submitting ) magically show up in the chart. The text input widget should be on top or just below each chart (there is more than one chart).

I have tried adding a widget, but when, after entering my comment, I rerun the chart, my widget naturally goes to blank and no annotation shows up in the chart.

I am sure this is a job for st.session_state() but I have no idea how to implement it.

It should be possible to annotate each chart independently with a different widget .

Thanks so much for your help!

Fabio

Hi @Fabio :wave:

It is certainly possible! Here’s an example that uses st.empty() and st.text_input() to achieve that behavior without st.session_state:

import streamlit as st
import plotly.graph_objects as go
import numpy as np

annotation_1 = st.text_input("Annotation text:", key="annotation_1")

animals = ["giraffes", "orangutans", "monkeys"]
fig_1 = go.Figure([go.Bar(x=animals, y=[20, 14, 23])])

chart_1 = st.empty()
chart_1.plotly_chart(fig_1)

if annotation_1:
    fig_1.add_annotation(
        text=annotation_1,
        xref="paper",
        yref="paper",
        x=0,
        y=1.1,
        showarrow=False,
        align="left",
        xanchor="left",
        font=dict(size=20, color="#242526"),
    )
    chart_1.plotly_chart(fig_1)


annotation_2 = st.text_input("Annotation text:", key="annotation_2")

x = np.arange(10)
fig_2 = go.Figure(data=go.Scatter(x=x, y=x ** 2))

chart_2 = st.empty()
chart_2.plotly_chart(fig_2)

if annotation_2:
    fig_2.add_annotation(
        text=annotation_2,
        xref="paper",
        yref="paper",
        x=0,
        y=1.1,
        showarrow=False,
        align="left",
        xanchor="left",
        font=dict(size=20, color="#242526"),
    )
    chart_2.plotly_chart(fig_2)

plotly-annotation

Happy Streamlit’ing! :balloon:
Snehan

2 Likes

Thanks @snehankekre!

It works! The “if” was the solution!

At the end, I used session state because I have a submit button to plot the charts.
image

I have one last problem. In the text input widget, when I enter my text, I get a “Press enter to apply” suggestion that in my case is misleading since I need to submit. Any way to make it go away? :slight_smile:

Many thanks

Fabio

@Fabio Glad I could help! :grinning_face_with_smiling_eyes:

The only time the “Press Enter to apply” prompt doesn’t appear is when the text input widget is within a form. When outside of a form, there is no way to disable the behavior. Here’s an example where you will not see the prompt:

import streamlit as st

with st.form("my_form"):
    annotation_1 = st.text_input("Annotation text:", key="annotation_1")
    submit = st.form_submit_button("Submit")

Best, :balloon:
Snehan

1 Like