Capture selected cell in streamlit-aggrid?

Is there a way to capture in python the clicked cell? I was only able to get the clicked row, but I need also the column index of the clicked cell.
The use case is to show additional information below the grid based on the clicked cell (needs to be done in Python, not JS).

Is this what you’re looking for?

import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder
import pandas as pd

# Define sample data
data = {
    'System Name': ['System A', 'System B', 'System C', 'System D'],
    'Value 1': [10, 20, 30, 40],
    'Value 2': [1, 2, 3, 4]
}
df = pd.DataFrame(data)

# Configure grid options using GridOptionsBuilder
builder = GridOptionsBuilder.from_dataframe(df)
builder.configure_pagination(enabled=True)
builder.configure_selection(selection_mode='single', use_checkbox=False)
builder.configure_column('System Name', editable=False)
grid_options = builder.build()

# Display AgGrid
st.write("AgGrid Demo")
return_value = AgGrid(df, gridOptions=grid_options)
if return_value['selected_rows']:
    system_name = return_value['selected_rows'][0]['System Name']
    st.write(f"Selected System Name: {system_name}")
else:
    st.write("No row selected")
2 Likes

Can we get this feature in st.data_editor plz?

you can also try my component: streamlit-table-select-cell for quick use without aggrid

If anyone is interested, I have a hacky method for selecting one or many cells in AgGrid tables and then retrieving their positions after. It uses JavaScript to add icons to cells. When you click to toggle the icons, a string is added to/removed from the cell value (without changing what the user sees). Then you parse the dataframe returned by AgGrid to get the cells that have this extra string. Works (at least) with streamlit-aggrid==0.3.4 to streamlit-aggrid==1.0.5 and streamlit between 1.35 and 1.39

import streamlit as st
import pandas as pd
import numpy as np

from st_aggrid import AgGrid, GridOptionsBuilder, JsCode, ColumnsAutoSizeMode

# an example based on https://www.ag-grid.com/javascript-data-grid/component-cell-renderer/#simple-cell-renderer-example
BtnCellRenderer = JsCode(
    """
class BtnCellRenderer {
    init(params) {
        this.params = params;
        this.eGui = document.createElement('div');
        this.eGui.style.position = 'relative';  // To position elements within the cell
        if (String(this.params.value).includes('[clicked]')) {
            this.params.value = this.params.value.replace('[clicked]','');
            this.params.originalValue = this.params.value;
            this.makeButton('πŸ“');
        } else {
            this.params.originalValue = this.params.value;
            this.makeButton('πŸ”');
        }
    }

    makeButton(symbol) {
        this.destroy();
        this.eGui.innerHTML = `
            <span id='click-button' style="position: absolute; left: 0; top: 50%; transform: translateY(-50%);">
                ${symbol}
            </span>
            <span style="margin-left: 24px;">${this.params.value}</span>`;
        this.eButton = this.eGui.querySelector('#click-button');
        this.btnClickedHandler = this.btnClickedHandler.bind(this);
        this.eButton.addEventListener('click', this.btnClickedHandler);
    }

    getGui() { return this.eGui; }

    refresh() { return true; }

    destroy() {
        if (this.eButton) { this.eGui.removeEventListener('click', this.btnClickedHandler); }
    }

    refreshTable(value) { this.params.setValue(value); }

    btnClickedHandler(event) {
        if(String(this.params.getValue()).includes('[clicked]')) {
            this.refreshTable(this.params.originalValue);
            this.makeButton('πŸ”');
        } else {
            this.refreshTable('[clicked]'+this.params.originalValue);
            this.makeButton('πŸ“');
        }
    }
};
"""
)

def make_aggrid(df):
    df = df.copy()

    # casting to string wasn't needed for streamlit-aggrid<=0.3.4
    df = df.astype(str)

    gb = GridOptionsBuilder.from_dataframe(df)
    for field in [
        "col1",
        "col2",
    ]:
        gb.configure_column(field, cellRenderer=BtnCellRenderer)

    grid_options = gb.build()

    response = AgGrid(
        df,
        gridOptions=grid_options,
        allow_unsafe_jscode=True,
        try_to_convert_back_to_original_types=False,  # otherwise we lose [clicked] strings in numerical columns
        columns_auto_size_mode=ColumnsAutoSizeMode.FIT_CONTENTS,
        height=150,
    )
    return response

np.random.seed(42)
data = np.random.rand(5, 5)
columns = ["col1", "col2", "col3", "col4", "col5"]

df = pd.DataFrame(data, columns=columns)

st.subheader("AgGrid (click at least one πŸ”)")
response = make_aggrid(df)

df = response["data"]
st.subheader("Raw output from AgGrid")
st.write(df)

result = []
for col in df.columns:
    for idx in df.index:
        if isinstance(df.at[idx, col], str) and df.at[idx, col].startswith("[clicked]"):
            result.append((col, idx))

st.subheader("Selected cells")
st.write(str(result))

I got an error when running your code:
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().