streamlit-aggrid icon indicating copy to clipboard operation
streamlit-aggrid copied to clipboard

Version 0.3.4 seems to have broken the clickable hyperlinks hack.

Open vovavili opened this issue 1 year ago • 13 comments

It seems that the trick to make links clickable doesn't work anymore in 0.3.4.

The code:

for col in links:
    js_hyperlinks = JsCode(
        """
        function(cell) {
            return `<a href="${cell.value}" target="_blank">Click me!</a>`
        }
        """
    )
    gb.configure_column(col, cellRenderer=js_hyperlinks)

On 0.3.3 - the tab of URLs is populated with 'Click me!' On 0.3.4 - <a href="link goes here" target="_blank">Click me!</a>

vovavili avatar Mar 03 '23 10:03 vovavili

I had to upgrade aggrid-react. And pure html responses won't work anymore. You'll need to use a cellRenderer.

More info:

https://github.com/ag-grid/ag-grid/issues/5427

PablocFonseca avatar Mar 03 '23 10:03 PablocFonseca

Got it. I guess that's unavoidable, so if change can be noted in the documentation the issue can be closed for now.

VovaViliLox avatar Mar 03 '23 14:03 VovaViliLox

I think to get JSX to work I need to import react somewhere - how have you solved it? Otherwise I get syntax errors.

To be explicit:

js_hyperlinks = JsCode(
        """
        function(cell) {
            return <a href={cell.value} target="_blank">Click me!</a>;
        }
        """
    )

does not work for me - I get a syntax error telling me "unexpected token < ".

mkleinbort-ic avatar Mar 07 '23 11:03 mkleinbort-ic

I'm running into the same problem, and I am sure many others will as well. Is there an "easy" way to turn a hyperlink as a string into something AG Grid will allow to be rendered as a hyperlink?

Thanks! Ed

ecal99 avatar Mar 08 '23 19:03 ecal99

I had to upgrade aggrid-react. And pure html responses won't work anymore. You'll need to use a cellRenderer.

More info:

ag-grid/ag-grid#5427

In the original post, he is using cellRenderer=js_hyperlinks

How is that not using a cellRenderer?

Your "more info" link is not really helpful for Python programers :'(

How do we return "JSX" in Python?

Do you know how to fix this? Can you explicitly say what is wrong with the code and how to fix it?

Thanks.

fplanque avatar Mar 10 '23 21:03 fplanque

I found my way to this thread as I was researching any leads on this same exact issue. Any ideas would be greatly appreciated.

kbarton1212 avatar Mar 10 '23 21:03 kbarton1212

Got it. I guess that's unavoidable, so if change can be noted in the documentation the issue can be closed for now.

@vovavili @VovaViliLox How did you fix it? Can you please show the code changes?

salman-moh avatar Mar 13 '23 06:03 salman-moh

This is a minimal cell renderer that you should be able to use instead of providing a function to the cellRenderer property.

class BoldCellRenderer {
  init(params) {
    this.eGui = document.createElement('span');
    this.eGui.innerHTML = '<b>'+params.value+'</b>';
  }
  getGui() {
    return this.eGui;
  }
}

https://plnkr.co/edit/vnQTtGG9k4oMR1Fm?open=index.jsx&preview

StephenCooper avatar Mar 13 '23 08:03 StephenCooper

This works, thank you.

For reference, my code looks like this:

gb = GridOptionsBuilder()
gb.configure_column(
    "URL", "URL",
    cellRenderer=JsCode("""
        class UrlCellRenderer {
          init(params) {
            this.eGui = document.createElement('a');
            this.eGui.innerText = 'SomeText';
            this.eGui.setAttribute('href', params.value);
            this.eGui.setAttribute('style', "text-decoration:none");
            this.eGui.setAttribute('target', "_blank");
          }
          getGui() {
            return this.eGui;
          }
        }
    """)
)

matkozak avatar Mar 13 '23 12:03 matkozak

@matkozak Worked for me too, thanks for that! Is there a way to somehow use python variables within the JSCode scope? The use case is that I have a table where one of the columns is a filename, but the link should direct to the full path of that filename which is defined elsewhere in the Python code.

yoeldk avatar Mar 27 '23 10:03 yoeldk

@yoeldk I took the awesome solution from @StephenCooper and @matkozak <3 and adjusted it to take some variables

  def link(linkText,url,linkColor):
      return JsCode(f"""
          class UrlCellRenderer {{
            init(params) {{
              let linkText = "{linkText}";
              let url = "{url}";
              let linkColor = "{linkColor}";
              url = !url || url.length === 0 ? params.value : url;      
              linkText = !linkText || linkText.length === 0 ? params.value : linkText;      
  
              this.eGui = document.createElement('a');
              this.eGui.innerText = linkText;
              this.eGui.setAttribute('href', url);
              this.eGui.setAttribute('style', "text-decoration:none");
              this.eGui.setAttribute('target', "_blank");
              this.eGui.setAttribute('style', `color:{linkColor};`);
            }}
            getGui() {{
              return this.eGui;
            }}
          }}
      """)

gudbrand3 avatar Jan 11 '24 20:01 gudbrand3

I get the error AttributeError: module 'streamlit.components.v1' has no attribute 'components' when I try the above code. Using streamlit-aggrid version 1.0.5 and streamlit version 1.36.0

Code:

def link(linkText,url,linkColor):
      return JsCode(f"""
          class UrlCellRenderer {{
            init(params) {{
              let linkText = "{linkText}";
              let url = "{url}";
              let linkColor = "{linkColor}";
              url = !url || url.length === 0 ? params.value : url;      
              linkText = !linkText || linkText.length === 0 ? params.value : linkText;      
  
              this.eGui = document.createElement('a');
              this.eGui.innerText = linkText;
              this.eGui.setAttribute('href', url);
              this.eGui.setAttribute('style', "text-decoration:none");
              this.eGui.setAttribute('target', "_blank");
              this.eGui.setAttribute('style', `color:{linkColor};`);
            }}
            getGui() {{
              return this.eGui;
            }}
          }}
      """)
# Create GridOptionsBuilder instance
gb = GridOptionsBuilder.from_dataframe(df)
gb.configure_default_column(editable=False, filter=True)
gb.configure_pagination(paginationAutoPageSize=False, paginationPageSize=12)
gb.configure_grid_options(domLayout='normal')
gb.configure_column("document_url",cellRenderer = link)

# Build grid options
grid_options = gb.build()

# Display the grid with custom options
st.title('AgGrid with HTML Content')
AgGrid(df, gridOptions=grid_options, enable_enterprise_modules=True, update_mode=GridUpdateMode.GRID_CHANGED)

arkp1612 avatar Jul 19 '24 14:07 arkp1612

Updating response = AgGrid(df,gridOptions=gb.build(),enable_enterprise_modules=True,update_mode= GridUpdateMode.GRID_CHANGED,allow_unsafe_jscode=True) makes it work

arkp1612 avatar Jul 19 '24 14:07 arkp1612