How to programatically update iframe src's in streamlit app (python)?

Summary

So basically I want to build an app that can display power bi reports. So, given that i have a list of power bi report embed urls, I want to programatically update the srcs (i.e. power bi report embed urls) inside the iframe element that i would pass in st.markdown() so that everytime i enter a new embed url, it automatically opens a new power bi report. Any way I can achieve that? Also, can anyone suggest me an alternative way to embed power bi reports if this doesn’t work out?

Here is what i am kinda trying to achieve

Code snippet:

embed_urls=['rep1.powerbi.com','rep2.powerbi.com','rep3.powerbi.com']
for i in embed_urls:
   st.markdown('<iframe src=i> </iframe>')


I know the piece of code above doesn’t make any sense but it is close to what I’m trying to achieve.

Two things:

First, if you want to include html in your app from markdown, you’ll need to include the optional argument unsafe_allow_html=True. Alternatively, you can use the components API to inject html, which comes in with its own iframe.

Second, you’ll need to format the string to inject the variable: st.markdown(f'<iframe src={i}> </iframe>').

So two solutions would be:

for i in embed_urls:
   st.markdown(f'<iframe src={i}> </iframe>', unsafe_allow_html=True)
for i in embed_urls:
   st.components.v1.html(f'<iframe src={i}> </iframe>')
1 Like

Just a follow-up question: Are both solutions -st.markdown including unsafe_allow_html and st.components.v1.html- technically the same resulting in an equivalent outcome? Or would you prefer one over the other under certain circumstances?

They differ in the layers created within the HTML of the app. The components API creates an iframe within which to put whatever HTML or script you are injecting. (So the above example would have both the iframe created by the components API and the typed-out iframe nested within, along with additional layers of divs.)

Also, if you are including some JavaScript, it doesn’t seem to run with the st.markdown solution, but does run with the components API solution.

So the more complicated you are getting with what you are injecting, the more likely you’d need to start working with the components API, maybe even up to the point needing to actually create a custom component.

1 Like