Display images in AgGrid table

Hi all,
this is my first post and I have to say I already love Streamlit :slight_smile:

My question is: can I display an image in a table created with the component AgGrid?

Thanks,
Vins

1 Like

I came looking for this feature. Currently displaying a peek of file paths, would be handy to display the related images as a thumbnail

Hi @Tobias_Schiele , @Vincenzo_Cacciatore , @Shinigami86 has already managed to do this. Check out this link: Ag-Grid component with input support - #63 by PablocFonseca

Cheers

Wow, thank you so much for your fast reply. That’s definitely something to work with. At the moment I am not able to use a JS solution as my image assets can exist outside of the streamlit host directory, thus they have to be loaded on the server-side. But hey, it’s a start! Maybe I can load each image, create a thumbnail on the fly and directly communicate the images to AgGrid. Thank you!

Hi,

I tried to adapt the code to display images in Ag-grid Table cell but It’s not working.

import pandas as pd
from st_aggrid import AgGrid, GridUpdateMode, DataReturnMode, JsCode
from st_aggrid.grid_options_builder import GridOptionsBuilder


df = pd.DataFrame({"Name": ["Elon", "Bill"],
                    "Image":[{'src':"https://fr.wikipedia.org/wiki/Elon_Musk#/media/Fichier:Elon_Musk_Royal_Society.jpg", 'alt':'Elon'},
                            {'src':"https://fr.wikipedia.org/wiki/Bill_Gates#/media/Fichier:Bill_Gates_-_Nov._8,_2019.jpg", 'alt':'Bill'},
                            ],
                    })

options_builder = GridOptionsBuilder.from_dataframe(df)

image_render = JsCode("""function (params) {
            this.params = params;
            this.img_render = document.createElement('div');
            
            this.img_render.innerHTML = `
                <img src=${this.params.src}
                    alt=${this.params.alt}
                    width="50"
                    height="50"
                >
            `;
            
            return this.img_render;
            }""")

options_builder.configure_column("Image",
        headerName="Image",
        cellRenderer=image_render)

grid_options = options_builder.build()

grid_return = AgGrid(df,
                    grid_options,
                    theme="streamlit",
                    allow_unsafe_jscode=True,
                    ) 

Any suggestions?

Hi @Marc_Richard, this has already been done. Check out this link: Ag-Grid component with input support - #63 by PablocFonseca

Cheers

Hi Shawn,
yes, I already tried this explore this example but I didn’t find how to code the right dataframe since in the post, he only shared the JScode and not the rest of the code. I am not sure why this is params.data.NATION_PATH and params.value because there is no example of the data column construction.
Any ideas?
thank you.

UPDATE:
my image url was not correct! It works now by using the example of PablocFonseca and the right image url.

import pandas as pd
from st_aggrid import AgGrid, GridUpdateMode, DataReturnMode, JsCode
from st_aggrid.grid_options_builder import GridOptionsBuilder


df = pd.DataFrame({"image_path":["https://upload.wikimedia.org/wikipedia/commons/thumb/e/ed/Elon_Musk_Royal_Society.jpg/800px-Elon_Musk_Royal_Society.jpg",
                                    "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Bill_Gates_-_Nov._8%2C_2019.jpg/390px-Bill_Gates_-_Nov._8%2C_2019.jpg"],
                    "Name":['Elon', 'Bill']
                    })

options_builder = GridOptionsBuilder.from_dataframe(df)


image_nation = JsCode("""function (params) {
        console.log(params);
        var element = document.createElement("span");
        var imageElement = document.createElement("img");
    
        imageElement.src = params.data.image_path;
        imageElement.width="40";
        imageElement.height="40";

        element.appendChild(imageElement);
        element.appendChild(document.createTextNode(params.value));
        return element;
        }""")
options_builder.configure_column('Name', cellRenderer=image_nation)


grid_options = options_builder.build()

grid_return = AgGrid(df,
                    grid_options,
                    theme="streamlit",
                    allow_unsafe_jscode=True,
                    ) 

Hi @Marc_Richard

Code Explanation: I have created a dataframe with 4 columns - this is fairly self-explanatory.
The 1st 2 images are stored locally on my hard drive in the mentioned path (which you can change if you plan to use local images). These need to be base64 and the function ‘ReadPictureFile’ does that conversion. For all local images, I iterrows of the dataframe and add the preliminary text ‘data:image/…’ - ref code

The last 2 images are directly accessed from the web and does not need any change in the image path column.

I hide the image path column, as this is not needed to be displayed.

I show the picture in the Face column.

Before trying the following code, you need to copy 2 images to your local folder and change the path and filenames of the 1st 2 images in the code. The code is below:

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

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="20";
            } else { imageElement.src = ""; }
            element.appendChild(imageElement);
            element.appendChild(document.createTextNode(params.value));
            return element;
            }""")


df = pd.DataFrame({'Name': ['Iron Man', 'Walter White', 'Wonder Woman', 'Bat Woman'],
                   'Face': ['', '', '', ''],
                   'ImgLocation': ['Local', 'Local', 'Web', 'Web'],
                   'ImgPath': ['D:/ShawnP/icon-im.png', 
                               'D:/ShawnP/icon-ww.png', 
                               'https://i.pinimg.com/originals/ab/26/c3/ab26c351e435242658c3783710e78163.jpg',
                               'https://img00.deviantart.net/85f5/i/2012/039/a/3/batwoman_headshot_4_by_ricber-d4p1y86.jpg'] })

if df.shape[0] > 0:
    for i, row in df.iterrows():
        if row.ImgLocation == 'Local':
            imgExtn = row.ImgPath[-4:]
            row.ImgPath = f'data:image/{imgExtn};base64,' + ReadPictureFile(row.ImgPath)

gb = GridOptionsBuilder.from_dataframe(df)
gb.configure_column('Face', cellRenderer=ShowImage)
gb.configure_column("ImgPath", hide = "True")

vgo = gb.build()
AgGrid(df, gridOptions=vgo, theme='blue', height=150, allow_unsafe_jscode=True )

Hope the above is understandable.

Cheers

aggimg

2 Likes

This solution no longer seems to work, nor does the one described here: Enhancing AgGrid table with Image Display in Streamlit Apps | by Avra | The Streamlit Teacher | Medium.

I’m getting an error in the streamlit app page " Component Error: Minified React error #31; visit https://reactjs.org/docs/error-decoder.html?invariant=31&args[]=[object%20HTMLImageElement] for the full message or use the non-minified dev environment for full errors and additional helpful warnings."

Does anybody know how to resolve this?

I figured it out myself. Here is what I did:

Custom cell renderer for Thumbnail column

thumbnail_renderer = JsCode(“”"
class ThumbnailRenderer {
init(params) {
this.eGui = document.createElement(‘img’);
this.eGui.setAttribute(‘src’, params.value);
this.eGui.setAttribute(‘width’, ‘100’);
this.eGui.setAttribute(‘height’, ‘auto’);
}
getGui() {
return this.eGui;
}
}
“”")

gb.configure_column(“Thumbnail”, “Thumbnail”, cellRenderer=thumbnail_renderer)

2 Likes

Can you provide more info? I’m trying to work with it but got undefined