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.

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?


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.


After pressing the page link.



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(

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='🗺️')


import streamlit as st


st.subheader('Detail Page')

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.