SJE is a custom Streamlit component, built to evaluate arbitrary Javascript expressions and return the result. It can become useful in doing certain functionalities which are simple things to do in JavaScript using the Web API, but unavailable or difficult to do in Streamlit. Examples include cookie management, writing to clipboard, getting device width (e.g. to check if we are on a mobile device), getting browser language, sharing something through Android’s share feature, knowing user agent, checking the battery and network status etc.
Here is an example
st.write(f"Screen width is {streamlit_js_eval(js_expressions='screen.width', key = 'SCR')}")
I will gradually add a more popular Web API to SJE in the form of Python functions so that the user does not have to see any JavaScript. Currently, we have Python wrapper for things like accessing cookies, the clipboard, and geolocation API. Here is an example of asking user’s location
# Returns user's location after asking for permission when the user clicks the generated link with the given text
location = get_geolocation()
Hope this very basic components helps other people and also make Streamlit even ore accessible, particularly with the recent emergence of Stlite, the great work of @whitphx to enable fully client-side Streamlit.
Sorry you ran into this. I don’t know much about the internals of callbacks in Streamlit and have not used them personally (or tested SJE against them).
As a quick fix, you can put the JS evaluation outside the callback function, like this:
import streamlit as st
from streamlit_js_eval import streamlit_js_eval
width = streamlit_js_eval(js_expressions='screen.width', want_output = True, key = 'SCR')
def disp_width():
to_display = f"Screen width is _{width}_"
print(to_display)
st.button("Display Screen Width", on_click=disp_width)
, which works on my machine. Does this fix work for you?
Thank you for the suggestion but I absolutelly need to get values from the localStorage many times from the code (using button callback).
If I look into the inspect console, I can see that the code tries to output the value but the value is not correctly received by the streamlit code. The error seems to be related to the reading of undefined properties.
Sorry, Marc. I played a bit with SJE source code and the issue is still there. It must have something to do with how callbacks work. I will create an issue in the Streamlit GitHub, but given that the components API is being rewritten, I am not sure there will be much effort on it
Can you tag someone from the Streamlit dev team here?
I tried this too and found it didn’t work using the callback. I also tried with a different JavaScript API component and encountered the same issue. So, it seems that components can’t be run within a widget callback.
This is an incredible component! I used it a few weeks ago in my app to get the latitude and longitude of my user. But now, it’s not working. I even tried the demo link multiple times, but the location feature isn’t returning any value. Please resolve this issue!
Hi. Sorry for the inconvenience. There has been no change in my code recently. Can you please confirm if it works on any other/older versions of Streamlit?
Thank you so much for the reply! I just tried it out on my phone and other laptop and it works just as perfectly as before. I believe there is an issue in my laptop. Thanks again, and sorry for the bother!
Hi @aghasemi,
thank you for your work and contribution.
I would like to ask you if I can implement an async javascript function inside the js_expressions argument and how to do it.
basically we receive data from an external authenticator system and I would like to fetch the attributes which are in the session page. Something like this:
async function getUser(){
const res = await fetch('myurl/Shibboleth.sso/Session')
const data = res.json()
document.getElementById("id").textContent = id}
This is the error logged in console: Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules at onDataFromPython
Great component! This provides a great workaround to dynamically sizing Altair combo charts, since use_container_width=True does not work with Altair combo charts.
Though streamlit_js_eval works great locally, when trying to run it on the streamlit cloud I get a ModuleNotFoundError even though I have listed it in my requirements.txt.
I am running streamlit v1.26.0 and streamlit_js_eval 0.1.5 locally, which I believe are the latest version. Does anyone have an idea why streamlit cloud can’t install the package even though it’s available in pip?