Ag-Grid component with input support

Ag-Grid for Streamlit is very helpful! I will use it in my project.

I have just begun to play around with this component and so far it has been great. Perhaps I am missing something but does anyone know how to set a valueFormatter for numeric and datetime columns such that NaN and NaT data respectively show up as blank cells? I am able to do it by injecting some conditional formatting code but I imagine there is a better way.

Any help would be great!

After looking at @mkleinbort 's code for enabling other functionality in aggrid and looking at aggrid’s documentation, I found that I could color rows using the following code snippet:

            jscode = JsCode("""
            function(params) {
                if (params.data.state === 'failed') {
                    return {
                        'color': 'white',
                        'backgroundColor': 'red'
                    }
                }
            };
            """)
            
            gridOptions = gb.build()
            gridOptions['getRowStyle'] = jscode

            grid_response = AgGrid(
                df,
                gridOptions=gridOptions,
                allow_unsafe_jscode=True,
           )

where df is the dataframe.

There are more recommended ways to do row styling, but this was a simple one to start with, given my lack of javascript experience.

Hope this helps,

Dinesh

1 Like

Is there a way to wrap header titles in the tables? I was able to wrap cell contents but couldn’t find an option to wrap header titles? Is that feature supported by streamlit_aggrid?

Native Aggrid seems to support it like here: Text Wrapping in ag-Grid Column Headers & Cells

Thanks.

Did you try to set headerComponentParams in grid options, like the example you sent?

you can use gridBuilder.configure_default_column(headerComponentParams=…) for this

Thank you! That worked. Was able to also right align the wrapped header titles (instead of the default left align).

The final config worked to wrap headers like so:

gb.configure_default_column(
        floating_filter=True,
        min_column_width=10,
        maxWidth=110,
        headerComponentParams={
            "template":
                '<div class="ag-cell-label-container" role="presentation">' +
                '  <span ref="eMenu" class="ag-header-icon ag-header-cell-menu-button"></span>' +
                '  <div ref="eLabel" class="ag-header-cell-label" role="presentation">' +
                '    <span ref="eSortOrder" class="ag-header-icon ag-sort-order"></span>' +
                '    <span ref="eSortAsc" class="ag-header-icon ag-sort-ascending-icon"></span>' +
                '    <span ref="eSortDesc" class="ag-header-icon ag-sort-descending-icon"></span>' +
                '    <span ref="eSortNone" class="ag-header-icon ag-sort-none-icon"></span>' +
                '    <span ref="eText" class="ag-header-cell-text" role="columnheader" style="white-space: normal;text-align: right;"></span>' +
                '    <span ref="eFilter" class="ag-header-icon ag-filter-icon"></span>' +
                '  </div>' +
                '</div>'
        }   
    )

Hello @PablocFonseca, this is a very useful component! Thanks for sharing it!
This might already have been asked somewhere else (so apologies for duplicates if any): is there a way to get the index of cells that have been modified? Thanks very much

1 Like

Hello @PablocFonseca, is there an example to add streamlit sliders or filters to adjust ag grid data.

I.e. streamlit slider to change calculated column in ag grid from 0-2

Greatly appreciate your help!

image

Thank you

@PablocFonseca, any solution for this?

Hi Streamlit community (and streamlit-aggrid users :slight_smile: )!

Has anyone found a way to clear a range selection? For example, if a user clicks outside the ag-grid. Is that even possible?

Thanks in advance.

Not yet…

I Looked into couple solutions, but I’m with very little time available to implement them. I’ll post here when it happens.

2 Likes

Hi @Josh_Meyer , I’ve made an example incorporating a few useful features. Please let me know if this is what you’re looking for or you have any questions!

import streamlit as st
import pandas as pd 
from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, DataReturnMode, JsCode

@st.cache(allow_output_mutation=True)
def load_data():
    df = pd.DataFrame({'fruit':['Apple', 'Banana'], 'unit_price':[50,25], 'num_units':[0,0], 'total_price':[0,0]})
    return df

loaded_data = load_data()

num_units = st.slider('Select Number of Units', 0, 130, 1)
loaded_data['num_units'] = num_units

js_calculate_total = JsCode("""

    function (params) {
        
         var unit_price = params.data.unit_price;
         var num_units = params.data.num_units;
         return (unit_price * num_units).toLocaleString(undefined, {minimumFractionDigits: 0, maximumFractionDigits: 0});

    }

""")

gb = GridOptionsBuilder.from_dataframe(loaded_data) #Infer basic colDefs from dataframe types
# Grid Builder configurations
gb.configure_default_column(groupable=True, value=True, enableRowGroup=True, aggFunc='sum', editable=False)
# Below, the first parameters are all the same as in the load_data dateframe, but the "header_name" is what is displayed and can be anything 
gb.configure_column("fruit", header_name='Fruit', pivot=True, sort='asc')
gb.configure_column("unit_price", header_name='Unit Price', sort='desc', type=["numericColumn","numberColumnFilter"], valueFormatter="data.estimatednotional_usd.toLocaleString(undefined, {minimumFractionDigits: 0, maximumFractionDigits: 0})", aggFunc='sum') # defines numeric column
gb.configure_column("total_price", header_name='Total Price', type=["numericColumn","numberColumnFilter"], editable=False, valueGetter=js_calculate_total) # uses custom value getter for calculated column
gridOptions = gb.build()
                            
grid_response = AgGrid(
        loaded_data,
        gridOptions = gridOptions,
        height=200,
        width='100%', # how much of the Streamlit page width this grid takes up
        update_mode=GridUpdateMode.MODEL_CHANGED,
        fit_columns_on_grid_load=True, # automatically fits all columns to be displayed in the grid in one view (doesn't always seem to work)
        allow_unsafe_jscode=True, # Set to True to allow the Javascript code to be injected
        enable_enterprise_modules=True, # enables right click and fancy features - can add license key as another parameter (license_key='string') if you have one
        key='select_grid', # stops grid from re-initialising every time the script is run
        reload_data=True, # allows modifications to loaded_data to update this same grid entity
        theme='light'
        )

Best
Ryan

1 Like

Hi,

is it possible to remove the column menus?

Thank you

try the following line when configuring the grid:

Hi, just thought to share this with others, in case anyone needs it:

I found a simple way to update changes made in an aggrid, to a pandas dataframe;
The code also provides a way to iterate through the aggrid. With this method, you can further selectively write to screen or update a database if you want/need to
To test this out, you will need to first create a simple csv file containing 2 columns: Name & Amt with a few entries.

The code is below:

Cheers

3 Likes

Thank you.

Is it possible to auto fit the table in a streamlit column?

Hi guys, how do I configure aggrid to enable RangeSelection?
I found out how to enable MultiSelection with checkboxes but it would make my life much easier if there would be a way to enable RangeSelection.

Best regards and massive thank you!
Petar

1 Like

Hi everyone,

I am trying the ag-grid component with a key (st.session_state.aggrid_key) and reload_data=True, to get the data to reload without redrawing (I want to avoid it disappearing for a fraction of a second) See my code below.

The button I am using works normally but after making an edit in ag-grid it stops working. Do you know why? Thanks in advance!

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

st.title('Football goals for each player')

if 'aggrid_key' not in st.session_state:
    st.session_state.aggrid_key = True
    st.session_state.df = pd.DataFrame({'players':['A', 'B', 'C', 'D'], 'goals':[20, 23, 19, 41]})

st.markdown('When you load the app the button works normally')

if st.button('Add one goal to each player'):
    st.session_state.df['goals'] = st.session_state.df['goals'] + 1

gb = GridOptionsBuilder.from_dataframe(st.session_state.df)       
     
gb.configure_column(field='players',editable=False)

gb.configure_column(field='goals',editable=True)

gb.configure_grid_options(stopEditingWhenCellsLoseFocus=True,headerHeight=30,rowHeight=30)

go = gb.build()

st.markdown('But if later you edit the ag-grid, the button stops working')

ag = AgGrid(
    dataframe=st.session_state.df,
    key=st.session_state.aggrid_key,
    reload_data=True,
    height=180,
    gridOptions=go,
    enable_enterprise_modules=True)

if (st.session_state.df['goals'] != ag['data'].iloc[:,1]).any():
    st.session_state.df['goals'] = ag['data'].iloc[:,1].values
    st.experimental_rerun()

Hello! I was wondering how did you get the conditional formatting for coloring the PRE% column? I’m currently trying to color a column cell red if the column value is <= 50% and green > 50%. My problem is that since the value is an object type not a float, I don’t know how to write the condition. I hope you could help!

Hello!,
Anyone has been able to add new rows to the Ag-grid with a small button?
I would like to do something as explained in this link: JavaScript Data Grid: Client-Side Data - Transaction Updates


2 Likes