Button inside a dataframe

Hi! Everyone, Is there a way to insert a button (not checkbox) inside a dataframe. So that for each row we have a separate button and when clicked we can perform some action.

1 Like

Hello Vedant :wave:,

As far as I know, you canā€™t directly add a button inside a (native) dataframe ā€“ There may be a hack but Iā€™m not aware of it! :smile:

Some questions:

  • Why wouldnā€™t the checkbox be a viable option?
  • Have you also tried other options such as streamlit-aggrid?

Thanks,
Charly

Iā€™m facing the same issue, I have a table where one column needs to redirect to a ā€˜detailsā€™ page with that rowā€™s info. I want to use st.page_link to go to the details page since it preserves st.session_state and is generally easy to use, or add a st.button with a st.switch_page callback. A link column doesnā€™t solve my problem because I would need to point to ā€œhttp://localhost:port/ā€ during development and change the link for a deploy, and to my knowledge there is no way to get the current url in streamlit (that doesnā€™t use JS or an equally hacky solution). Honestly, a generic callback option when clicking a table cell would be the best and easiest (I think) solution. Iā€™ll try to use streamlit-aggrid but it would be better to have a native option for streamlit.

You can use a checkbox instead of a button. With 1.35, it has a feature to select a single row, column, etc.

Here is a sample demo.

image


After pressing the page link.

image


streamlit_app.py

import streamlit as st
import pandas as pd


data = {
    'Country': ['United States', 'Canada', 'Germany', 'France', 'Japan'],
    'Capital': ['Washington, D.C.', 'Ottawa', 'Berlin', 'Paris', 'Tokyo']
}


df = pd.DataFrame(data)
st.title('Countries and Their Capitals')

event = st.dataframe(
    df,
    on_select='rerun',
    selection_mode='single-row'
)

if len(event.selection['rows']):
    selected_row = event.selection['rows'][0]
    country = df.iloc[selected_row]['Country']
    capital = df.iloc[selected_row]['Capital']

    st.session_state['country_data'] = {'country': country, 'capital': capital}
    st.page_link('pages/detail.py', label=f'Goto {country} Page', icon='šŸ—ŗļø')

pages/detail.py

import streamlit as st


st.set_page_config(layout='centered')


st.subheader('Detail Page')
st.write(st.session_state['country_data'])
1 Like

Thanks for the code snippet, @ferdy! :hugs:

I actually used checkboxes (as in a boolean column in an editable table) to solve this issue before the selection feature was available, but I donā€™t think this is the best solution yet.

My main issue with checkboxes is that from a design pov they imply that more than one option can be selected, which is not the desired behavior. A radio button would be better, but then I would need another button to confirm the userā€™s selection, which is an unneeded button press. The best solution, in my opinion, still is a button row.

Iā€™ll look into the select row and column feature as soon as I have some time, maybe thereā€™s a way to achieve this behavior without using checkboxes.

That belief is incorrect. Have a look on this discussion at ux stack.

One nice feature of this table is the ability to clear the selection.

The link you presented reinforces what I said. Checkboxes imply zero or more selections, but in my use case only one option should be selected, which triggers a redirect to another page. Radio buttons would be more appropriate since options are mutually exclusive, but it still feels strange clicking a radio button to go to another page.

You are incorrect again. You said

Would like to see a solution as wellā€¦ Aggrid is cool, but I want to use actual streamlit buttons, not HTML rendered ones