Links in datatable - Multipage App

Nice site!

As far as I can tell, supporting non-text / dropdown data types is still on the list for dash-table, but unfortunately it’s not currently on the roadmap. Seems like once it’s on the roadmap the plotly devs still need to figure out expected behavior for other table actions (see issue #166) – e.g. how to filter, sort, etc.

In the meantime, I came up with a little bit of a hack that adds links into the a column after the table has been loaded. I am doing this using a clientside callback. In the following code snippets, I assume that all links share a common baseHref and the differentiation for the URI is contained as the text content of column 0. From your screenshot, the first row link would point to a relative url: "/route/to/SISM-CHR-001"

Step-by-step:

  1. Create a javascript file in the app’s assets folder (e.g. assets/app-ui.js):
if (!window.dash_clientside) {
    window.dash_clientside = {};
}

const baseHref = "/route/to/";

// create the "ui" namespace within dash_clientside
window.dash_clientside.ui = { 
    // this function should be used in the callback whenever the table viewport has changed
    replaceWithLinks: function(trigger) {
        // find all dash-table cells that are in column 0
        let cells = document.getElementsByClassName("dash-cell column-0");

        cells.forEach((elem, index, array) => {
            // each cell element should be modified with a new link
            // elem.children[0].innerText contains the link information, which we append to a specified route on our server
            elem.children[0].innerHTML =
                '<a href="' +
                baseHref +
                elem.children[0].innerText +
                '">' +
                elem.children[0].innerText +
                "</a>";
        });

        // arbitrary return.. callback needs a target
        return true;
    }
}

Just change baseHref to your desired routing.

  1. In your Dash layout, add a hidden div that will be the Output target of the callback.
layout = ...
    ...,
    html.Div(id='table-hidden-target', style={'display': 'none'}),
    ...
  1. Add a dash clientside callback to execute our function “replaceWithLinks” every time the table viewport changes.
...
app.clientside_callback(
    ClientsideFunction('ui', 'replaceWithLinks'),
    Output('table-hidden-target', 'children'),
    [Input('[ENTER-YOUR-TABLE-ID]', 'derived_viewport_data')]
)
...

That should be it!

Looks something like this (in the image, I actually generated links using text from column-0 to modify column-1, but the idea should be the same):
before: image
after: image

This hack works as expected when you only have the one table on a page. If that changes, you’ll need to modify the javascript to find the correct table and modify the children cells appropriately. Hope this helps; the clientside callbacks really gave a lot of capability to end users (for example, how to get around file size limits in downloading data in browser – I posted an example for that in the csv download thread as well)

4 Likes