Ag-Grid component with input support

Yes, it was! thank you, Daniel

This component is the best. Really appreciate all the work done here.
I am using a grid that updates cell colors when the value is updated. I followed the “Highlight Editions” example on the sample app and it works great. My question is, how do I change the background color? It seems to always be a teal color (see below). My JavaScript abilities are not good :slight_smile: Any help appreciated!

Hi @drew ,

Regarding styling the streamlit-aggrid component:

  • If you want to change the whole theme, use the theme parameter in the AgGrid() function. If I remember correctly, the default theme should match the Streamlit theme.

  • If you want to make very specific changes to the style, use the custom_css parameter in the AgGrid() function. For example, I change my grid size with custom_css={".ag-theme-streamlit": {"--ag-grid-size": "5px"}}, but you can try playing with other AgGrid css variables.

Hope that helps :slight_smile:

Hey Mr_John,

Check out this thread

grafik
I’m having the same Issue as @apex_yu
The cellstyle JsCode

cellstyle_jscode = JsCode("""
        function(params){
            if (params.data.status_path == 'red') {
                return {
                    'color': 'black',
                    'backgroundColor' : 'red'
            }
            }
            if (params.data.status_path == 'orange') {
                return{
                    'color'  : 'black',
                    'backgroundColor' : '#FE5A1D'
                }
            }
            if (params.data.status_path == 'green') {
                return{
                    'color'  : 'black',
                    'backgroundColor' : 'green'
                }
            }
        };
        """)

The dataframe

df2Test  = pd.DataFrame({"a":["test"]*len(halden), "b": time, "c":tons})

And the Gridoptionsbuilder

gd = GridOptionsBuilder.from_dataframe(df2Test)
        gd.configure_columns(['a', 'b', 'c'], cellStyle=cellstyle_jscode)
        gd.configure_column('c', width = 150, wrapText = True)
        gd.configure_column('a', wrapText = True, width = 250, headerCheckboxSelection = True, pre_selected_rows = preselectedRows)
        gd.configure_column('b', width = 120, wrapText = True)
        gd.configure_grid_options(rowHeight=120, columnWidth=190)
        gd.configure_selection(selection_mode = 'multiple', use_checkbox = True)

Sorry, the deletion function test failed. I am not familiar with JS

Thanks for bringing this up. When I have used text wrapping in this excellent component with auto height in the cell contents, I find that the text breaks within the words rather than at spaces between words:

https://dajavous-thebcd-public-app-ztufun.streamlitapp.com/

Is there a way to fix this via setting white-space: normal; so that line breaks only occur between words? The blog for Ag-Grid includes some detailed template information for the header rows but not the cell contents:

Thanks @Max_Witteman for the great solution.
One side note for the delete function, I had to add to its ‘configure_column’ the parameter ‘checkboxSelection=True’ so that user can use it to select the row to delete.

anyone can help me?
i need chance cellstyle based on a conditional, but, i dont know how i’ll do this.

i know how define a conditional on pandas, but not on ag grid

i am trying to add image field into my Ag-Grid object by following this example but with success.
i am retrieving data from SQL server and convert it to dataframe than try to add the image but is not working.
i mage exist on my drive
c:\Users\test\desktop\pictures\pic1.png

where is my error ?

code:


show_image=JsCode("""function(params){
           var element = document.createElement("span");
            var imageElement = document.createElement("img");
        
            if (params.data.image_path) {
                imageElement.src = params.data.image_path;
                imageElement.width="20";
            } else {
                imageElement.src = "";
            }
            element.appendChild(imageElement);
            element.appendChild(document.createTextNode(params.value));
            return element;
            }""")
    gb.configure_column('pic', cellRenderer=show_image)

it depends on the field name or column that you want to make a condition for it let say based on your post you want to change the color or the record based on the field name ESTOQUE

inside the Ag-Grid object you need to follow these steps.

let say you have a datafarme df

code:


from st_aggrid import GridOptionsBuilder,JsCode
dg = GridOptionsBuilder.from_dataframe(df)
change_color = JsCode("""
          function(params){
            if(params.data.ESTOQUE ====4){
               
                   return {
                        'background':'#f17b7b'
                   }
           }           
           if(params.data.ESTOQUE ====2){
               
                 return {
                       'background':'#ffffff'
                  }
            
           }
""")

gridoptions = gd.build()
gridoptions['getRowStyle']=change_color

grid_table = AgGrid(df,gridoptions, allow_unsafe_jscode = True)

Hi @Max_Witteman , I’m interested to know how you implemented default values for added rows and also the pop confirmation for delete button. Thank you so much!

Hi, I am trying to use a list inside JScode to check my if condition. But whenever I pass the the list, all the values of the data frame disappear. How can I use a list to check if my params.value equals to one of the value in the list, rather an a single value.

```
value = [1,2]
cellstyle_jscode = JsCode(f"""
const error = {value}   
    function (params) {{  
        const hasValue = error.includes(params.value)          
            if (hasValue === true){{
                return {{
                    'backgroundColor': 'red',
                }}
            }}
    }}

""")
gb = GridOptionsBuilder.from_dataframe(failed_indices_df)
gb.configure_columns(failed_indices_df, cellStyle=cellstyle_jscode,)
gridoptions = gb.build()
response = st.write(
    grid_return=AgGrid(
        failed_indices_df,
        gridOptions=gridoptions,
        height=600,
        width=600,
        reload_data=False,
        theme="balham",
        fit_columns_on_grid_load =True,
        allow_unsafe_jscode=True,
        enable_enterprise_modules=True,
       #update_mode=GridUpdateMode.MANUAL,
    )
)

Local images need to be base64. Here’s an example you can test out (Display images in AgGrid table - #8 by Shawn_Pereira).

Cheers

I tried your answer with the connection with SQL server DB the picture doesn’t show in the AgGrid table.
But if i tried to read the image based on the giving path it works and the ReadPictureFile() return the correct file.

Note: if i try your code it works perfectly with the giving dataframe but once i tried to use it inside my SQL table it crash and doesn’t display the picture.

what could be the problem and how to display image inside the AgGrid table i needed in order to accomplish my project.

File path: C:/Users/admin/Desktop/Python/imgs/david-wong.png

code:

import pyodbc
import pandas as pd
import numpy as np

import streamlit as st

#  aggrid pckgs
from st_aggrid import AgGrid,GridOptionsBuilder,JsCode
from st_aggrid import GridUpdateMode,DataReturnMode

from io import BytesIO

import base64


#  connect to DB
@st.experimental_singleton
def connect_db():
    try:
        con = pyodbc.connect(
            driver = "ODBC Driver 17 for SQL Server",
            Server="127.0.01",

            DATABASE="FTF",
            UID="XXXX",
            PWD="XXXXXXX",
        )
        cursor = con.cursor()
    except Exception as e:
        st.write("error is: {}".format(e))
    return con

con = connect_db()

def ReadPictureFile(wch_fl):
    try:
        return base64.b64encode(open(wch_fl, 'rb').read()).decode()

    except:
        return ""

ShowImage = JsCode("""function (params) {
            var element = document.createElement("span");
            var imageElement = document.createElement("img");
        
            if (params.data.ImgPath != '') {
                imageElement.src = params.data.ImgPath;
                imageElement.width="100";
            } else { imageElement.src = ""; }
            element.appendChild(imageElement);
            element.appendChild(document.createTextNode(params.value));
            return element;
            }""")

df = pd.read_sql_query('''select ID,
name,
ImgPath
from [FTF].[dbo].[profile_info] 
''',con)

df['ImgPath'] = df['ImgPath'].replace(np.nan,'NULL')
if df.shape[0] > 0:
    for i, row in df.iterrows():
        # if row.ImgLocation == 'Local':
        imgExtn = row.ImgPath[-4:]

    
        if imgExtn == '.png':
            st.write(imgExtn)
            row.ImgPath = f'data:image/{imgExtn};base64,' + ReadPictureFile(row.ImgPath)
            st.write(row.ImgPath)



with con.cursor()as cur:
    gb = GridOptionsBuilder.from_dataframe(df)
    gb.configure_default_column(editable=True,min_column_width=2)
    gb.configure_column('Face', cellRenderer=ShowImage)
    
    gb.configure_grid_options(rowHeight = 100)
    vgo = gb.build()
    AgGrid(df, gridOptions=vgo, height=1000, allow_unsafe_jscode=True )

Well, I don’t have SQL server DB nor have access to your data.

Just before your “if df.shape[0]…” statement, insert a st.dataframe(df) to check what comes back from the database into your ImgPath column of your data frame.

If valid image paths come back, do they actually point to the exact image location? You will need to test this.

Also, does your ImgLocation column correctly classify the image as ‘Local’ for the image that resides on your disk?

Cheers