nicedouble / StreamlitAntdComponents

A Streamlit component to display Antd-Design
https://nicedouble-streamlitantdcomponentsdemo-app-middmy.streamlit.app/
MIT License
440 stars 29 forks source link

on_change does not work in streamlit==1.39.0 #69

Open ChazRuler opened 1 month ago

ChazRuler commented 1 month ago

Streamlit==1.39.0 streamlit_antd_components==0.3.2

maggie1121 commented 1 month ago

sac.buttons callback args is still broken.

def callback(*args, **kwargs):
    print(f"callback args: {args}")

def test():
    key = uri + f"_{name}_buttons"
    print(f"key: {key}")
    sac.buttons(
        [sac.ButtonsItem(uri) for uri in uris],
        index=None,
        size='xs',
        key=key,
        on_change=callback, args=(key,)
    )

The above code is broken with an upgrade if streamlit1.36.0, the callback args print out empty tuple: ()

ChazRuler commented 1 month ago

Streamlit==1.39.0 should use Streamlit's custom component onchange callback API,I modified the files in the directory streamlit_antd_components/utils/component_func.py according to the official method as follows, and it worked. `def component(id, kw, default=None, key=None, on_change=None): if key is not None and key not in st.session_state: st.session_state[key] = default

_on_change = None if on_change is not None: if key is None: st.error("You must pass a key if you want to use the on_change callback") else: def _on_change(): return on_change(key)

if key is not None: st_value = convert_session_value(id, st.session_state[key], kw.get('kv'), kw.get('return_index')) kw.update({"stValue": st_value}) else: kw.update({"stValue": None}) return component_func(id=id, kw=json.loads(json.dumps(kw, cls=CustomEncoder)), default=default, key=key, on_change=_on_change if _on_change is not None else None)`

KuanHsiaoKuo commented 1 month ago

Let me refine this—two modifications are needed to make it work:

For widgets.buttons.buttons, need to add the on_change parameter when returning, like this:

# in def buttons, pre as below:
# return component(id=get_func_name(), kw=kw, default=default, key=key)
return component(id=get_func_name(), kw=kw, default=default, key=key, on_change=on_change)

As you mentioned, modify the utils.component_func.component function.

def component(id, kw, default=None, key=None, on_change=None):
    point_function()
    if key is not None and key not in st.session_state:
        st.session_state[key] = default

    _on_change = None
    if on_change is not None:
        if key is None:
            st.error("You must pass a key if you want to use the on_change callback")
        else:
            def _on_change():
                return on_change(key)

    if key is not None:
        st_value = convert_session_value(
            id, st.session_state[key], kw.get('kv'), kw.get('return_index')
        )
        kw.update({"stValue": st_value})
    else:
        kw.update({"stValue": None})

    return component_func(
        id=id,
        kw=json.loads(json.dumps(kw, cls=CustomEncoder)),
        default=default,
        key=key,
        on_change=_on_change if _on_change is not None else None
    )

Currently, I am using it without any issues, and it perfectly triggers the corresponding function only when the button is clicked. Here is a sample of my code:

def show_rules():
    def callback(*args, **kwargs):
        print(f"callback args: {args}, { st.session_state.get('sac.rule_buttons')}")
        rule_buttons_callbacks[st.session_state['sac.rule_buttons']]['callback']()
    rule_buttons_callbacks = {
        'Choose New CSV': {
            'callback': select_tables_in_config_dialog,
            'icon': "floppy2"
        },
    }
    sac.buttons([
        sac.ButtonsItem(label=label, icon=details['icon'])
        for label, details in rule_buttons_callbacks.items()
    ],
        key='sac.rule_buttons',
        use_container_width=True,
        index=None,
        on_change=callback,
        color="#00A355")
tpougy commented 2 weeks ago

I'm affected by this issue too. Any news from the maintainers about a fix release on this issue?