-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clear clickable component value on rerun? #7
Comments
Hi @lansing. I'm not a Streamlit expert but I think that giving a specific key to a component leads to having this component's state persist from one session to another. In your code, if you replace the static keys with different values for each session, you'll be able to increase the counter (I understand that's what you want). Here is one way to do it: import random # <------
import streamlit as st
from st_click_detector import click_detector
html = """
<a href="#" id="event">First Click me</a>
"""
with st.sidebar:
clicked_result = click_detector(html, key=str(random.randint(0, 1e12))) # <------
if clicked_result != "":
st.session_state.number = 0
with st.container():
clicked_result_container = click_detector(html, key=str(random.randint(0, 1e12))) # <------
if clicked_result_container != "":
st.session_state.number = 0
st.number_input("Then Increment me", value=1, key="number")
st.write(f"st.session_state_number: {st.session_state.number}") |
I'm having the same issue as OP, and I don't believe the above fixes the problem: making the key a random ID every time doesn't seem to register the click at all. What I'm trying to achieve (and I think OP) is:
|
FWIW I got around this by keeping track of what links were clicked (I believe similar to what OP is describing): import streamlit as st
from st_click_detector import click_detector
if "links_clicked" not in st.session_state:
st.session_state.links_clicked = {}
content = "<a href='some-url'>My Link</a>"
link_clicked = click_detector(content, key="key")
if link_clicked != "" and link_clicked not in st.session_state.links_clicked:
# Do something only once here...
st.session_state.links_clicked[link_clicked] = True This let the click detector act as more of an event listener 😄 |
@nikodraca this is also how I solved it, however there is one slight problem as you cannot check if the link is clicked a second time as its value doesn't change in between. There is a solution to this by setting the value back to null on the frontend side, according to this discussion, however this triggers rerendering of the app twice and caused issues for me in combination with other widgets. I did solve this in a hacky way yesterday by changing the onclick functionality as follows: for (let i = 0; i < links.length; i++) {
if (links[i].id !== "") {
links[i].onclick = function (): void {
if (curr_val == links[i].id) {
curr_val = links[i].id + '#'
} else {
curr_val = links[i].id
}
Streamlit.setComponentValue(curr_val)
}
}
} What this does is it keeps in mind the last value clicked and if the current clicked value is the same as the last value, it adds a "#" to the end. Then on the python side the value for link_clicked will change between Hope this helps! 🤞 |
Hey @nikodraca , you solution doesn't seem to register the click at all. Could you help out please? |
|
The code does not seem to work. The curr_val is always empty and the condition |
I believe it would be better if a feature can be added to detect single clicks, provided there are no technical issues. Using a single-click detector as a selector by tracking the last clicked element with session state is easier than using a selector to detect single clicks, as discussed previously. |
I think we can simply reset the clicked state by rerunning and using a different key. Here is my solution (modified from nikodraca's solution): import streamlit as st
from st_click_detector import click_detector
import time
if "link_key1" not in st.session_state:
st.session_state.link_key1 = 0
if "link_key2" not in st.session_state:
st.session_state.link_key2 = 10000
content1 = "<a href='some-url1' id='id1'>My Link1</a>"
content2 = "<a href='some-url2' id='id2'>My Link2</a>"
link_clicked1 = click_detector(content1, key=st.session_state.link_key1)
link_clicked2 = click_detector(content2, key=st.session_state.link_key2)
if link_clicked1 != "":
# Do something here...
st.write('link1 clicked')
st.session_state.link_key1 += 1
time.sleep(1)
st.rerun()
else:
# Do something here...
st.write('link1 not clicked')
if link_clicked2 != "":
# Do something here...
st.write('link2 clicked')
st.session_state.link_key2 += 1
time.sleep(1)
st.rerun()
else:
# Do something here...
st.write('link2 not clicked') It can support multiple click-detectors and won't listen to every event. |
mylank solution for multiple clicks vivien000#7
@mylank @PawelFaron |
I have observed that, once a clickable component is clicked, the value of the component (now set to the
id
of thea
that was clicked) is persisted indefinitely for the session. In other words, if I click a link insideclickable
withid="event"
, then the value ofclickable
in the Python script will beevent
not just for the rerun following the click, but for every rerun afterwards as I interact with other components.I assume this is the intended behavior, but it's an issue for my use case. I only want to trigger some behavior one time after the clickable is clicked (essentially I just want the same behavior as
st.button
). Is that possible with this component? I'm pretty new to Streamlit so maybe I'm missing something obvious.I created a super simple streamlit app to reproduce the behavior and demonstrate my desired use case:
https://github.com/lansing/st-click-detector-issue
In the above app, I want to click one of the links, updating the
session_state
that the number box is bound to (changing the number to0
), then continue to increment the number box. But that's not possible because the clickable code block is getting executed on every subsequent rerun, resetting my number to0
.I am currently using a hacky workaround that stores a
last_clicked_event
in thesession_state
and treats the clickable as un-clicked if its value is equal tost.session_state.last_clicked_event
, but that obviously means you can't click the same event twice in a row.Thanks, appreciate the contribution.
The text was updated successfully, but these errors were encountered: