How to make dash ag grid table cells hyperlinked

I am exploring the new dash ag grid tables, using it instead of dash datatable . Been trying to make one column hyperlinked. Earlier I was doing it like

href = f"{dashboard_name}/?primary_metric={gspc_code}&secondary_metric={row['long_title']}&graph_type=line_graph&primary_scale=primary_linear&secondary_scale=secondary_linear"
link = html.A(f"{row['Indicator']}", href=href)

what would be an dash ag grid equivalent for the same. Tried with

"cellRenderer": 'markdown'

inside columnDefs for ag grid. But it doesnt work since the hyper referenece link will be dynamic. Any help is appreciated. Thanks in advance.

2 Likes

Hello @jayeetamukherjee,

You should take a look here:

With it you can create custom links inside the grid easily, while also keeping your data relatively easy to read.

Thank you so much for the reference. I have almost zero knowledge in javascript, am unable to make it work using the example mentioned in the documentation. Can we use any javascript function or callback function to achieve the same. Thanks

The data in the first post is where the things will be?

Hi. Sorry for the late reply. I’ve been able to make it work as a stand alone dash app. Now, I need to use this inside a Django Dash project. How can I add the external javascript inside a djanodash app?Thanks.

If dash_ag_grid does not provide a built-in way to make text a hyperlink, then it is a good candidate for a feature.

  • simple version: parse cells for existing <a> tags
  • advanced version: help people construct the <a> tags for a column

It would be easier for me to write my own flexboxy table than implement some custom cell renderer.

We provide a cellRenderer for markdown text, you’d just pass it as a markdown link, and if you want it to open in a new window, pass the columnDef linkTarget=“_blank”

2 Likes

I recently updated the docs to show how to do this with Markown. (The PR is not live yet, but check back in a couple days)

Here’s one of the new examples. It will render html tags if you include dangerously_allow_code=True
If you just use markdown syntax for the links [link name](link) it’s not necessary to allow html to render.

import dash_ag_grid as dag
from dash import Dash, html, dcc

app = Dash(__name__)


columnDefs = [
    {"field": "make"},
    {"field": "link", "headerName": "Link opens new tab", "linkTarget":"_blank"},
    {"field": "image"},
]

rain =  "![alt text: rain](https://www.ag-grid.com/example-assets/weather/rain.png)"
sun = "![alt text: sun](https://www.ag-grid.com/example-assets/weather/sun.png)"

rowData = [
    {
        "make": "**Toyota** in bold",
        "link": "[Example](#)",
        "image": f"{rain} {rain} {rain} {rain} {rain}"
    },
    {
        "make": "_Ford_ in italics",
        "link": "[Google](https://google.com)",
        "image": sun,
    },
    {
        "make": "***Porsche*** in both",
        "link":   '<a href="#" target="_blank">Link to new tab</a>',
        "image": rain
    },
]

app.layout = html.Div([
        dag.AgGrid(
            id="cell-renderer-grid-5",
            columnSize="sizeToFit",
            columnDefs=columnDefs,
            defaultColDef={"cellRenderer": "markdown"},
            rowData=rowData,
            dangerously_allow_code=True
        ),
])


if __name__ == "__main__":
    app.run(debug=True)
3 Likes

@AnnMarieW @jinnyzor thank you!

I think I found a bug where markdown renderer is not displaying zero values. I don’t want to make too much of a fuss about it in its own post because I’m running plotly 5.13 and can’t upgrade rnow, but I did want to report it. [Of course, I got around this by applying the renderer to my link column specifically]

No Renderer

Markdown Renderer

Hello, I followed this suggestion and my links became clickable, but even if I specify the link to target “blank” (as in the code below), the links open in the same window/tab as the dashboard, and I wanted a separate tab/window. Could you please advise?

columnDefs = [
    {'field': 'Гео', 'width': 100},
    {'field': 'Сектор', 'width': 100},
    {'field': 'Организация', 'width': 200},
    {'field': 'Ссылка', 'width': 200, 'linkTarget': '_blank'},
    {'field': 'Язык', 'width': 50},
    {'field': 'Сообщение', 'width': 700},
    {'field': 'Время', 'width': 200},
]


##Initialize the app

app = Dash()


#№ App layout

app.layout = html.Div([
    html.Div(children = 'Новостной наблюдатель.'),
    html.Hr(),
    #html.Div(children = 'Период появления новостей равен последним трём часам.'),
    html.Br(),
    html.Div(children = 'Свежие новости.'),
    dag.AgGrid(
        style = {"height": 1000, "width": 1900},
        id = 'controls-and-table1',
        rowData = articles.to_dict('records'),
        columnDefs = columnDefs,
        defaultColDef = 
            {
                "filter": True,
                "wrapText": False,
                "autoHeight": True,
                "cellRenderer": "markdown"
            },
        columnSize = "sizeToFit",
        columnSizeOptions = {
            'defaultMinWidth': 100
        },
        dashGridOptions = {"animateRows": True},
        dangerously_allow_code = True
    ),
    html.Br(),
    html.Div(children = 'Выберите период отбора свежих новостей в часах:', style={'width': '400px'}),
    html.Div(
       children = dcc.RadioItems(options = ['1', '3', '6', '12', '24'], value = '1', id = 'controls-hours'),
       style={'width': '300px'}
    ),
])
articles['message_url'] = \
        '<a href=' + '"' + articles['message_url'] + '"' + ' target="_blank">' + articles['message_url'] + '</a>'

Hi @alexeymosc and welcome to the dash community :slight_smile:

If you are using the markdown renderer, the links need to be in markdown format, for example:

"[Google](https://google.com)"

1 Like

@alexeymosc,

Another thing to know is that you need to pass linkTarget to the columnDef, check out more here:

1 Like

Hi and thank you!

For some reason changing link style didn’t help.

#articles['message_url'] = \
    #    '<a href=' + '"' + articles['message_url'] + '"' + ' target="_blank">' + articles['message_url'] + '</a>'
articles['message_url'] = \
      '[' + articles['message_url'] + ']' + '(' + articles['message_url'] + ')'
...
{'field': 'Ссылка', 'width': 200, 'linkTarget': '_blank'},
...

The links are rendered clickable but again open in the same tab.

Could it be that other options to AdGrid override being opened in a new tab?

dag.AgGrid(
        style = {"height": 1000, "width": 1900},
        id = 'controls-and-table1',
        rowData = articles.to_dict('records'),
        columnDefs = columnDefs,
        defaultColDef = 
            {
                "filter": True,
                "wrapText": False,
                "autoHeight": True,
                "cellRenderer": "markdown"
            },
        columnSize = "sizeToFit",
        columnSizeOptions = {
            'defaultMinWidth': 100
        },
        dashGridOptions = {"animateRows": True},
        dangerously_allow_code = True
    ),

Thank you! I did that,

...
{'field': 'Ссылка', 'width': 200, 'linkTarget': '_blank'},
...

but the links open in the same tab. Thanks for the docs, I consulted with them.

A package version:

pip show dash
WARNING: Ignoring invalid distribution -illow (c:\users\...\anaconda3\lib\site-packages)
Name: dash
Version: 3.0.3
Summary: A Python framework for building reactive web-apps. Developed by Plotly.
Home-page: https://plotly.com/dash
Author: Chris Parmer
Author-email: chris@plotly.com
License: MIT
Location: c:\users\burna\anaconda3\lib\site-packages
Requires: Flask, importlib-metadata, nest-asyncio, plotly, requests, retrying, setuptools, typing-extensions, Werkzeug
Required-by: dash_ag_grid

You need to also pass cellRenderer: markdown

I have made this as well

defaultColDef = 
            {
                "filter": True,
                "wrapText": False,
                "autoHeight": True,
                "cellRenderer": "markdown"
            },

without effect.
I have checked the behaviour on two machines, running an app in Chrome, the same.

Let me give you a minimal example. Do you experience the link to google being opened in a new tab?

#!~/env/bin/python
# coding: utf-8

## Dash board

import dash_ag_grid as dag
from dash import Dash, dcc, html, dash_table, callback, Input, Output
import pandas as pd

## Make a dummy dataframe

articles = pd.DataFrame(
    {
        'Гео': ['0'],
        'Сектор': ['0'],
        'Организация': ['0'],
        'Ссылка': ['https://www.google.com/'],
        'Язык': ['0'],
        'Сообщение': ['0'],
        'Время': ['0']
    }
)

columnDefs = [
    {'field': 'Гео', 'width': 100},
    {'field': 'Сектор', 'width': 100},
    {'field': 'Организация', 'width': 200},
    {'field': 'Ссылка', 'width': 200, 'linkTarget': '_blank'},
    {'field': 'Язык', 'width': 50},
    {'field': 'Сообщение', 'width': 700},
    {'field': 'Время', 'width': 200},
]


##Initialize the app

app = Dash()


#№ App layout

app.layout = html.Div([
    html.Div(children = 'Новостной наблюдатель.'),
    html.Hr(),
    #html.Div(children = 'Период появления новостей равен последним трём часам.'),
    html.Br(),
    html.Div(children = 'Свежие новости.'),
    dcc.Interval(
            id = 'interval-component',
            interval = 5000, # in milliseconds
            n_intervals = 0
    ),
    dag.AgGrid(
        style = {"height": 1000, "width": 1900},
        id = 'controls-and-table1',
        rowData = articles.to_dict('records'),
        columnDefs = columnDefs,
        defaultColDef = 
            {
                "filter": True,
                "wrapText": False,
                "autoHeight": True,
                "cellRenderer": "markdown"
            },
        columnSize = "sizeToFit",
        columnSizeOptions = {
            'defaultMinWidth': 100
        },
        dashGridOptions = {"animateRows": True},
        dangerously_allow_code = True
    ),
    html.Br(),
    html.Div(children = 'Выберите период отбора свежих новостей в часах:', style={'width': '400px'}),
    html.Div(
       children = dcc.RadioItems(options = ['1', '3', '6', '12', '24'], value = '1', id = 'controls-hours'),
       style={'width': '300px'}
    ),
])


## Callbacks

@callback(
    Output(component_id = 'controls-and-table1', component_property = 'rowData'),
    Input(component_id = 'controls-hours', component_property = 'value'),
    Input(component_id = 'interval-component', component_property = 'n_intervals')
)
def update_table1(hours, n_intervals):

    articles = pd.DataFrame(
        {
            'Гео': ['0'],
            'Сектор': ['0'],
            'Организация': ['0'],
            'Ссылка': ['https://www.google.com/'],
            'Язык': ['0'],
            'Сообщение': ['0'],
            'Время': ['0']
        }
    )
    
    articles['Ссылка'] = \
        '[' + articles['Ссылка'] + ']' + '(' + articles['Ссылка'] + ')'

    return articles[[
            'Гео',
            'Сектор',
            'Организация',
            'Ссылка',
            'Язык',
            'Сообщение',
            'Время'
        ]].to_dict('records')


## Run

if __name__ == '__main__':
    
    app.run(debug = True, host= '0.0.0.0', port = 7072)
    

Try putting the renderer onto the columnDef directly.

Ok, I tried this (only one line changed in code):

{'field': 'Ссылка', 'width': 200, 'linkTarget': '_blank', 'cellRenderer': 'markdown'},

no errors, but, alas, it works as before. (

1 Like

@alexeymosc
Try running the first example on this page. It works fine for me:

1 Like

Thank you! Your example works fine. I tried researching my code, and I just did this:

{"field": "link", "headerName": 'Ссылка', 'width': 200, 'linkTarget': '_blank'},

instead of earlier version

{"field": "Ссылка", 'width': 200, 'linkTarget': '_blank'},

It looks that when I made the field “field” written in latin characters, and used a header description in slavic, it started working!

Best regards!
Alexey

2 Likes