Ag-Grid component with input support

Hey Kiran, I have a couple ideas for hacks for this.

The closest thing to what you are looking for is probably the onCellClicked grid option. This option can take some JsCode that will be executed whenever a cell is clicked. I don’t know javascript well enough to tell you what that code should be, though. Using the GridOptionBuilder, this would look something like:
gb.configure_grid_options( onCellClicked = JsCode(“”“function(event) { <your code> }”“”) )

The second idea would be to mess with the master-detail stuff. The aggrid documentation for this is here. To use this for st_aggrid, you can use the gridOptionBuilder to set the option masterDetail to True, and set detailCellRendererParams to a dictionary which at least includes “getDetailRowData” : <Some JSCode to access the text>.

This may look something like:
gb.configure_grid_options(
masterDetail=True,
detailCellRendererParams={
“detailGridOptions”: {
“columnDefs”: <your code>,
},
“getDetailRowData”: JsCode(“”“function(params){
params.successCallback(params.data.VulnerabilityImpact);
}”“”),
},
)

Not sure if that is exactly right because VulnerabilityImpact column has just strings instead of its JSON objects, but you can probably figure it out from there.

Finally, I think there might be grid options that works like onCellClicked but for double click and right click, but I don’t remember their names or how they work.

(Look at this Angular Data Grid: Grid Events (ag-grid.com))

Hello,

Thank you all for this! Just wondering, is grouping and hovering enabled from this package?

Angular Data Grid: Column Groups (ag-grid.com)

ag-Grid Styling & Appearance: Row Styles

Hi @crsca, you can try out my sample code for grouping as below, and modify it for your use thereafter:

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


df=pd.DataFrame({ "Name": ['Paul', 'Gina'], "Age": [43, 35], "Inducted": [True, False], 
                  "Firm": ['Google', 'Microsoft'], "JDesc": ['Analyst', 'Programmer']})
gridOptions = GridOptionsBuilder.from_dataframe(df)
gb = gridOptions.build()

gb['columnDefs'] = [ { 'headerName': 'Personal Dtls', 'children': [ { 'field': 'Name' }, { 'field': 'Age' } ] }, 
                     { 'headerName': 'Partially', 'children': [{'field': 'Inducted'}] }, 
                     { 'headerName': 'Profession Dtls', 'children': [ { 'field': 'Firm' }, { 'field': 'JDesc' } ] }, 
                     { 'children': [{'field': 'Processed'}] } ]
                    
dta = AgGrid(df, gridOptions=gb, height=350, theme="blue", update_mode=GridUpdateMode.SELECTION_CHANGED)

Cheers

1 Like

@Shawn_Pereira this worked perfectly! Thank you!

Just a quick follow up, how would you center the header names and is it possible to customize their background color?

I tried adding headerClass and cellClass, and still no luck.

gb[“columnDefs”] = [
{
“headerName”: “Personal Dtls”,
“headerClass”: “ag-center-header”,
“cellClass”: “ag-center-cell”,
“children”: [{“field”: “Name”}, {“field”: “Age”}],
},
{“headerName”: “Partially”, “children”: [{“field”: “Inducted”}]},
{
“headerName”: “Profession Dtls”,
“children”: [{“field”: “Firm”}, {“field”: “JDesc”}],
},
{“children”: [{“field”: “Processed”}]},
]

1 Like

Hi @crsca, colours seem possible, but I didn’t get the time to try it out. Will let you know if that happens.

Cheers

Hi @Shawn_Pereira,

Following this interesting post, do you know if it’s possible to add a onCellClicked grid event that enlarge the image in a popup window ? The goal would be to click on a cell and expand the image like this.

Thank you in advance for your response,
Best regards,

Louis

Hi @Louis_Monier, pls refer the code below for an implementation of onCellClicked. You could probably write the image into the new window (myWin) and expand it with JS. I didn’t get a chance to try it as yet. Do give it a shot at your end on the basis of the following code.

Hi @Kiran_K, below is an implementation of a browser window (instead of a popup). You can easily modify the JS to further suit your purpose.

Clicking on the Name field gives a standard JS popup; clicking on the Topics field gives a browser-based popup. I have inserted paragraph tags in the 3rd topic to illustrate line breaks. You can change the text attributes in the secondary browser window as required.

Copy & paste the code to test it out, and then repurpose it for your needs.

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

st.set_page_config(layout = "wide", initial_sidebar_state = "expanded")
t1 ="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
t2 = "Congue quisque egestas diam in arcu. Libero nunc consequat interdum varius sit amet mattis vulputate. Vitae congue mauris rhoncus aenean vel elit scelerisque mauris. Nunc sed velit dignissim sodales ut eu sem integer vitae. Ut pharetra sit amet aliquam id diam. Tristique risus nec feugiat in. Non quam lacus suspendisse faucibus interdum. Faucibus ornare suspendisse sed nisi lacus sed viverra. Aliquet lectus proin nibh nisl"
t3 = "Urna cursus eget nunc scelerisque viverra mauris in aliquam. <p>Dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. </p> Vestibulum sed arcu non odio euismod lacinia at. Massa id neque aliquam vestibulum morbi blandit cursus risus. Tincidunt tortor aliquam nulla facilisi cras. Nisi est sit amet facilisis magna. Id velit ut tortor pretium viverra suspendisse potenti. Blandit libero volutpat sed cras ornare arcu dui vivamus. Sit amet purus gravida quis blandit turpis cursus."

df=pd.DataFrame({ "Name": ['Erica', 'Rogers', 'Malcolm'], 'Topics': [t1, t2, t3], "Age": [43, 35, 57]})

clicked_name_cell_func = "function(params) { alert(params.node.data.Name); };"
clicked_topic_cell_func = """function (params) { 
    let myWin = window.open("Topic", "wid", "toolbar=no,menubar=no,location=no,status=no,height=285,width=500, left=450,top=175");
    myWin.document.write("<span style='font-size: 24px; color:red;'>" + params.data.Topics + "</span>");
    myWin.focus();
                                                }"""

gridOptions = GridOptionsBuilder.from_dataframe(df)
gridOptions.configure_column("Name", headerTooltip='Click to see cell data', onCellClicked=JsCode(clicked_name_cell_func))
gridOptions.configure_column("Topics", headerTooltip='Click to see cell data', onCellClicked=JsCode(clicked_topic_cell_func), maxWidth=600)

gridOptions.configure_default_column(editable=True)
gb = gridOptions.build()

dta = AgGrid(df, gridOptions=gb, height=200, allow_unsafe_jscode=True, theme="blue",
             update_mode=GridUpdateMode.SELECTION_CHANGED & GridUpdateMode.MODEL_CHANGED)

Cheers

3 Likes

@Shawn_Pereira

Awesome, it worked! I have applied this to the entire table using the below code.

def clicked_cell_func(col_name):
    return f"function(params){{ alert(params.node.data.{col_name}); }};"


for col_index, col_name in enumerate(df.columns):
    gd.configure_column(f"{col_name}", headerTooltip="Click to sort data",
                        onCellDoubleClicked=JsCode(clicked_cell_func(col_name)), maxWidth=800)
3 Likes

I would like to add a row filled with the same values as the previous row. Can you help me to do that? Thanks :pray:

Hi!

Have you found a solution for this? I am looking for the exact same but could not figure a way out yet.

Thanks in advance!

Hi @robert.k and @Joao_Alves

Here’s the sample code to insert a new row in Aggrid and set it to the previous row.

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


df=pd.DataFrame({ "Name": ['Erica', 'Rogers', 'Malcolm', 'Barrett'], "Age": [43, 35, 57, 29]})

add_row_func = """function(e) 
                    { let api = e.api; 
                      let rowIndex = e.rowIndex + 1; 
                      
                      let vnme = e.data.Name;
                      let vage = e.data.Age;

                      api.applyTransaction({addIndex: rowIndex, add: [{'Name': vnme, 'Age': vage}]}); 

                      };"""
ShowAddBtn = JsCode("function addBtn(params) { return '<button style=background-color:green;>+</button>'; }")

gridOptions = GridOptionsBuilder.from_dataframe(df)
gridOptions.configure_column('+', headerTooltip='Add new row', editable=False, filter=False, 
                            onCellClicked=JsCode(add_row_func), cellRenderer=ShowAddBtn,
                            autoHeight=True, wrapText=False, lockPosition='left', pinned='left', 
                            sorteable=False, suppressMenu=True, maxWidth = 50)
gridOptions.configure_default_column(editable=True)
gb = gridOptions.build()

dta = AgGrid(df, gridOptions=gb, height=350, allow_unsafe_jscode=True, theme="blue",
             update_mode=GridUpdateMode.SELECTION_CHANGED)

Cheers

1 Like

Thanks for the code @Shawn_Pereira!

My question would be, if anybody already found a solution to add a new row after clicking on a separate button? So instead of having an own column that has “add” in each row I am looking for a single st.button that would take over the task and add a new row.

Do you have any ideas?

Your help is much appreciated, thanks in advance!

Thanks a lot @Shawn_Pereira !
It’s not exactly what I wanted (modal popup that enlarges the image). But my friend chatGPT and I found a solution eventually !
Best

Hi @robert.k , do you mean something like:

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

if "df" not in st.session_state:
    st.session_state.df = pd.DataFrame()

if st.session_state.df.shape[0] == 0:
  st.session_state.df=pd.DataFrame({ "Name": ['Erica', 'Rogers', 'Malcolm', 'Barrett'], "Age": [43, 35, 57, 29]})
gridOptions = GridOptionsBuilder.from_dataframe(st.session_state.df)
gridOptions.configure_default_column(editable=True)
gb = gridOptions.build()

if st.button("Add New Row"):
  st.session_state.df.loc[len(st.session_state.df)] = ['', 0]
  st.experimental_rerun()

dta = AgGrid(st.session_state.df, gridOptions=gb, height=250, allow_unsafe_jscode=True, theme="blue",
             update_mode=GridUpdateMode.SELECTION_CHANGED)

Cheers

1 Like

Brilliant!! Thanks so much! Exactly what I was looking for :slight_smile:

Now seeing the solution, “of course, why not simply adjusting the datafame?” :wink: Very nice solution!

1 Like

thanks for the code @Shawn_Pereira !!

Thanks for this component @PablocFonseca I am using it here App for searching the arxiv & it checks for valid Github links! - #14 by robmarkcole

When grouping and aggregating, i lose the formatting of the aggregated amount. Any assistance is appreciated.

Thanks

Here is a snapshot of my code:
gb = GridOptionsBuilder()
gb.configure_column(“date”, type=[“dateColumnFilter”,“customDateTimeFormat”],
custom_format_string=‘MM-yyyy’, rowGroup=True, hide=True, sort=‘desc’)
gb.configure_column(“amount”, type=[“numericColumn”,“numberColumnFilter”,“customNumericFormat”],
valueFormatter=“data.AuctionAmt.toLocaleString(‘en-US’);”, precision=0, pivot=True, aggFunc=“sum”,
filter=‘agNumberColumnFilter’
)

gb.configure_grid_options(groupDisplayType=‘multipleColumn’, suppressAggFuncInHeader=True)

gb.configure_pagination()
gb.configure_side_bar()
#gb.configure_default_column(enablePivot=True, groupable=True, value=True, enableRowGroup=True, aggFunc=“sum”, editable=False)
gridOptions = gb.build()

AgGrid(data[[‘date’, ‘amount’]],
gridOptions=gridOptions, enable_enterprise_modules=True, allow_unsafe_jscode=True)

this is what I want, thank you!

1 Like

Use the CustomCSS feature to set the attributes of the classes of the header cell, then you can both change the background color and the centering of text.

custom_css = {
    ".ag-header-cell-label": {"justify-content": "center"},
    ".ag-header-group-cell-label": {"justify-content": "center"}
    }

grid_response = AgGrid(
 ...
    custom_css=custom_css,
)