gamcoh / st-card

Streamlit component for UI cards
https://pypi.org/project/streamlit-card/
MIT License
116 stars 19 forks source link

Multiple On Clicks run when I click on only one. #22

Closed zimmer44 closed 10 months ago

zimmer44 commented 10 months ago

Hi @gamcoh,

Thanks for making this package I like it a lot.

I ran into an issue with using the on_click feature of the card.

from streamlit_card import card

import base64

with open('transparent.png', "rb") as f:
    data = f.read()
    encoded = base64.b64encode(data)
data = "data:image/png;base64," + encoded.decode("utf-8")

from streamlit_card import card

hasClicked = card(
  title="Button 1",
  text="Some description",
  image=data,
  on_click=lambda: print('hi'),
  key='first'
)

hasClicked2 = card(
  title="Button 2",
  text="Some description",
  image=data,
  on_click=lambda: print('hi again'),
  key='second'
)

Here is a quick example that reproduces the issue I am having.

When you click on the card that is titled "Button 1" it will print "hi".

Afterwards if you then click on the card titled "Button 2" instead of expected output to be "hi again" it will instead print "hi" then "hi again".

I believe it has something to do with the __init__.py file checking

if clicked:
    on_click()

Which after clicking on a card it is set to true, but also stays true when pressing another card resulting in both on_clicks to execute.

Thanks again for making this super useful just struggling with figuring out how exactly the on_click portion works.

gamcoh commented 10 months ago

Hi, this is not an issue, this is by design

When you change a state in streamlit, it reloads all component with the changed states, resulting in multiple firing of on_click function.

Check out this link for more explanation https://docs.streamlit.io/library/advanced-features/session-state

gamcoh commented 10 months ago

If you don't want this, you could use some python / streamlit tricks to get that out of the way :

zimmer44 commented 10 months ago

Thanks for the quick response.

Is there a way to have the card behave like a checkbox? So it is more of a toggle when clicking it then unclicking it essentially?

gamcoh commented 10 months ago

Yes, but that should be handle python side, you'll have to code something like that :

# Somewhere in your app initialization
st.session_state["has_clicked"] = False

...
clicked = card(...)
if clicked:
  st.session_state["has_clicked"] = not st.session_state["has_clicked"]
zimmer44 commented 10 months ago

I'm still a bit confused on how to get this working. Appreciate the help, but don't want to waste your time.

Again thanks for making the card package I'll use it without the click feature.

tihomir-trifonov commented 8 months ago

Hey @zimmer44 ,

had same issue, solved it with st-click-detector from https://github.com/vivien000/st-click-detector and jinja2 html template.