Error creating a dash table with a column containing buttons with links to download a file

I have created a dash application in which you need to add a tab with a table. there is no problem in this. the problem is that I can create a table with data like: int, str, bool. however, I have a column with a link for which I need to create an additional column with a button to download (upload) a log file from this link. here is my code:

data = {'Time': dates, 'Strategy': strategies, 'Job': jobs, 'Status': statuses, 'Link to log': logs}
df = pd.DataFrame(data)
def render_download_link(link):
    return html.A('Download log', href=link, target='_blank')
df['Download_log'] = df['Link to log'].apply(render_download_link)
layout = html.Div([
    dash_table.DataTable(
        data=df.to_dict('records'),
        columns=[
            {'name': 'Time', 'id': 'Time'},
            {'name': 'Strategy', 'id': 'Strategy'},
            {'name': 'Job', 'id': 'Job'},
            {'name': 'Status', 'id': 'Status'},
            {'name': 'Link to log', 'id': 'Link'},
            {'name': '', 'id': 'Download_log', 'presentation': 'markdown'}
        ],
        style_data_conditional=[
                {
                    'if': {'column_id': 'Download_log'},
                    'textAlign': 'center'
                }
            ]
    )
])

however, when loading the application, an error of incorrect data format is displayed and the application does not work. please tell me what options there are. thanks

Hello @alesia,

Welcome to the community!

First off, you are trying to render a dash component with markdown, this is not how it works, I don’t think. It should either be markdown or raw html.

With that being said, you just need to change your function to be making a raw html string or markdown text.

Or, you could try taking a look at AG Grid.

This has a markdown section:

Or you could create your own component with just the link in the data and then it just renders the component as a link.

Anyways, there is a lot of flexibility with whatever you decide.

I’m new to this and it will be difficult to do it without an example. can you give an example of how to create a raw html string or markdown text? I would be very grateful for your help

if i am trying to paste in dash_table dcc.markdown, i receive error: Invalid argument data[0].Column 1 passed into DataTable.
Expected one of type [string, number, boolean].
How to decide it?

To use markdown, all you have to do is tell it to presentation markdown and then create a markdown string.

You could also just use a cellClick event to determine what file should be downloaded.

1 Like

I decided it in this way:
@callback(
Output(‘modal_content’, ‘children’),
Input(‘datatable-interact’, ‘active_cell’),
State(‘datatable-interact’, “data”)
)
def display_log_file_contents(active_cell, data):
if active_cell:
row = active_cell[‘row’]
column = active_cell[‘column_id’]
if column == ‘Logfile’:
log_file = data[row][column]
with open(log_file, ‘r’, encoding=‘utf-8’) as f:
log_contents = f.read()
return html.Div([
html.P(log_file),
html.Hr(),
html.Br(),
html.Pre(log_contents)
])
else:
return ‘’
return ‘’

but if I have a table with pagination, it has several pages, when you click on a file located on the second page, a file located on the same line only on the first page is loaded. is there any way to solve this?

Hmm, there doesnt seem to be a way because it is just determining where in the table you are clicking.

Maybe give AG Grid a try, it is a little more straightforward:

Give this a shot:

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

app = Dash(__name__)

data = {'Time': dates, 'Strategy': strategies, 'Job': jobs, 'Status': statuses, 'Link': logs}
df = pd.DataFrame(data)
app.layout = html.Div([
    dag.AgGrid(
        rowData=df.to_dict('records'),
        columnDefs=[
            {'field': 'Time'},
            {'field': 'Strategy'},
            {'field': 'Job'},
            {'field': 'Status'},
            {'headerName': 'Double Click to Display', 'field': 'Link',
             'cellStyle': {'textAlign': 'center', 'cursor': 'pointer'}}
        ],
        id='file_displayer'
    ),
    html.Div(id='log')
])

@app.callback(
    Output('log', 'children'),
    Input('file_displayer', 'cellDoubleClicked'),
    prevent_initial_call=True
)
def showFile(cell):
    if cell['colId'] == 'Link':
        log_file = cell['value']
        with open(log_file, 'r', encoding='utf-8') as f:
            log_contents = f.read()
        return html.Div([
            html.P(log_file),
            html.Hr(),
            html.Br(),
            html.Pre(log_contents)
        ])
    return no_update

if __name__ == '__main__':
    app.run(debug=True)

You could always just have the link be clickable too.

thanks for help

Thanks very much

1 Like