How to Edit Cell of Streamlit AgGrid's Row?

Question:

I have already created AgGrid by loading data from a csv file. I am adding rows one by one via an external button. But when I try to edit the line I added, it disappears. I would be very grateful if you could help me where the error is. The codes are as follows.

import pandas as pd
import streamlit as st
from st_aggrid import AgGrid, GridUpdateMode,  JsCode
from st_aggrid.grid_options_builder import GridOptionsBuilder
import sys
import os
import altair as alt
from streamlit.runtime.legacy_caching import caching

def data_upload():
    df = pd.read_csv("data.csv")
    return df

if 'grid' in st.session_state:
    grid_table = st.session_state['grid']
    df = pd.DataFrame(grid_table['data'])
    df.to_csv(“data.csv”, index=False)
else:
    df = data_upload()

gd = GridOptionsBuilder.from_dataframe(df)
gd.configure_column("Location", editable=True)
gd.configure_column("HourlyRate", editable=True)
gd.configure_column("CollaboratorName", editable=True)

gridOptions = gd.build()


button = st.sidebar.button("Add Line")

if "button_state" not in st.session_state:
    st.session_state.button_state = False

if button or st.session_state.button_state:
    st.session_state.button_state = True
    data = [['', '', 0]]
    df_empty = pd.DataFrame(data, columns=['CollaboratorName', 'Location', "HourlyRate"])
    df = pd.concat([df, df_empty], axis=0, ignore_index=True)
    df.to_csv(“data.csv”, index=False)
    gd= GridOptionsBuilder.from_dataframe(df)


grid_table = AgGrid(df,
                    gridOptions=gridOptions,
                    fit_columns_on_grid_load=True,
                    height=500,
                    width='100%',
                    theme="streamlit",
                    key= 'unique',
                    update_mode=GridUpdateMode.GRID_CHANGED,
                    reload_data=True,
                    allow_unsafe_jscode=True,
                    editable=True
                    )
if 'grid' not in st.session_state:
    st.session_state['grid'] = grid_table
else:
    grid_table_df = pd.DataFrame(grid_table['data'])
    grid_table_df.to_csv(“data.csv”, index=False) 

You can see the running app from here enter image description here

Asked By: Hilal

||

Answers:

That happened because of your if button: statement. Streamlit button has no callbacks so any user entry under a st.button() will always reload the page so you end up losing the data, to prevent this, you can either initialize a session state fo your button or you can use st.checkbox() in place of st.button().

In this case I am going to fix your code by initializing a session state of the button.

def data_upload():
    df = pd.read_csv("data.csv")
    return df

st.header("This is AG Grid Table")
if 'grid' in st.session_state:
    grid_table = st.session_state['grid']
    df = pd.DataFrame(grid_table['data'])
    df.to_csv('data.csv', index=False)

else:
    df = data_upload()

gd = GridOptionsBuilder.from_dataframe(df)
gd.configure_column("Location", editable=True)
gd.configure_column("HourlyRate", editable=True)
gd.configure_column("CollaboratorName", editable=True)

gridOptions = gd.build()

def update():
    caching.clear_cache()

button = st.sidebar.button("Add Line")       

# Initialized session states                 # New code     
if "button_state" not in st.session_state:
    st.session_state.button_state = False

if button or st.session_state.button_state:
    st.session_state.button_state = True            # End of new code
    
    data = [['', '', 0]]
    df_empty = pd.DataFrame(data, columns=['CollaboratorName', 'Location', "HourlyRate"])
    df = pd.concat([df, df_empty], axis=0, ignore_index=True)
    gd= GridOptionsBuilder.from_dataframe(df)
    df.to_csv('data.csv', index=False)
    gridOptions = gd.build()

grid_table = AgGrid(df,
                    gridOptions=gridOptions,
                    fit_columns_on_grid_load=True,
                    height=500,
                    width='100%',
                    theme="streamlit",
                    key= 'unique',
                    update_mode=GridUpdateMode.GRID_CHANGED,
                    reload_data=True,
                    allow_unsafe_jscode=True,
                    editable=True
                    )
if 'grid' not in st.session_state:
    st.session_state['grid'] = grid_table

grid_table_df = pd.DataFrame(grid_table['data'])
grid_table_df.to_csv('data.csv', index=False)

I think your code should work fine now with regards to the button issue.

Answered By: Jamiu Shaibu

This one has a different approach but the goal could be the same.

Two radio buttons are created, if value is yes new line will be created, if value is no there is no new line.

If you want to add a new line, select yes and then add your entry. Then press the update button in the sidebar.

enter image description here

If you want to edit but not add a new line, select no, edit existing entry and then press the update button.

Code

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


def data_upload():
    df = pd.read_csv("data.csv")
    return df


def show_grid(newline):
    st.header("This is AG Grid Table")
    df = data_upload()

    if newline == 'yes':
        data = [['', '', 0]]
        df_empty = pd.DataFrame(data, columns=['CollaboratorName', 'Location', "HourlyRate"])
        df = pd.concat([df, df_empty], axis=0, ignore_index=True)

    gb = GridOptionsBuilder.from_dataframe(df)
    gb.configure_default_column(editable=True)
    grid_table = AgGrid(
        df,
        height=400,
        gridOptions=gb.build(),
        fit_columns_on_grid_load=True,
        allow_unsafe_jscode=True,
    )
    return grid_table


def update(grid_table):
    grid_table_df = pd.DataFrame(grid_table['data'])
    grid_table_df.to_csv('data.csv', index=False)


# start
addline = st.sidebar.radio('Add New Line', options=['yes', 'no'], index=1, horizontal=True)
grid_table = show_grid(addline)
st.sidebar.button("Update", on_click=update, args=[grid_table])
Answered By: ferdy
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.