📣 Dash v1.8.0 release - dcc.Graph updates, markdown & link support in DataTable, and more

Update: version 1.16 has been released since this was posted.

Dash 1.8.0 is a minor release improving dcc.Graph responsiveness on page and parent element resize and adds markdown support to the DataTable.

Changelog
Dash v1.8.0

Highlights

Previous Releases

Delving Deeper

Graph Responsiveness
The Plotly.js library allows the container to be resize on window resize but does not react to parent element resize, which can lead to some undesired behavior. To help usability, in addition to using the figure.layout.autosize and config.responsive flags in Plotly, it is now possible to override thedcc.Graph behavior by passing responsive=False|True|'auto'(default).

  • If responsive=True: will be responsive to both window and parent resize and will override any default behavior from config/figure
  • If `responsive=False: will be not be responsive even if it could have been.
  • If responsive='auto' (default): will be responsive on both window and parent resize if it would otherwise have been responsive on page resize, will not be responsive otherwise.

Table Markdowns
The table now has a new presentation='markdown' option on columns that can be used with type='text'. The table will parse the text as markdown and display the result.

import dash
from dash_html_components import Div
from dash_table import DataTable

app = dash.Dash(__name__)

data=[
    dict(a=''' ```javascript
return 20;
    ```
'''), # need to dedent the ``` for actual usage
    dict(a='''An image\n
![Plotly](https://global.discourse-cdn.com/business7/uploads/plot/original/2X/7/7957b51729ad7fd9472879cd620b9b068d7105bb.png)'''),
    dict(a='''
_italics_\n
**bold**\n
~~strikethrough~~
'''),
    dict(a='''Nested table
Statement | Is it true?
--- | ---
This page has two tables | yes
This table has two rows | no
This is an example of tableception | yes
'''),
    dict(a='[Dash documentation](https://dash.plot.ly)')
]

app.layout = Div([
    DataTable(
        columns=[
            dict(name='a', id='a', type='text', presentation='markdown'),
        ],
        css=[
            dict(selector='img[alt=Plotly]', rule='height: 50px;')
        ],
        data=data
    ),
])

app.run_server(debug=True)

3 Likes

Hi,

I am trying to get links embedded in the dash datatable. I was informed that this new version (1.8.0) now includes markdowns (links, images etc).
I was hoping for an example script that shows how to have links embedded in a datatable when reading columns from a pandas dataframe.
I then hope to have the table filterable - will the links still be supported with filtering?
I would really appreciate some help with the syntax on this issue.

Thanks
Georgia

1 Like

One question about the responsive attribute, does this also work with transitions on the parent element?

@Gbw-lucite Links are supported through the Markdown syntax. In markdowns, links take the form [display_name](url) with both parts mandatory. If you have no meaningful name to display, just use the url like so: [url](url).

You can optionally add a hover title/description for the link like so: [display_name](url "title").

There are many good resources online for the Markdown syntax, here’s a demo from the 3rd party used by the DataTable to render markdowns: https://jonschlinkert.github.io/remarkable/demo/. That said, many sources of information exist and not all markdown implementations are created equal and some disparities are to be expected if looking at other sources.

For filtering, the table filters on the raw value of the field. The link in the example above (dict(a='[Dash documentation](https://dash.plot.ly)')) will match both Dash and plot.ly.

Sorting is also done on the raw value of the field, not the displayed value. If for a certain column all rows contain similarly formatted links, this will behave the same as if sorting on the display value.

import dash
from dash_html_components import Div
from dash_table import DataTable

from pandas import DataFrame

def f(row):
    return "[{0}]({0})".format(row["url"])

d = {
    'id': [1,2,3,4,5,6],
    'url': [
        'www.google.com',
        'dash.plot.ly',
        'plot.ly',
        'community.plot.ly',
        'altavista.com',
        'yahoo.com'
    ]
}
df = DataFrame(data=d)
df["link"] = df.apply(f, axis=1)
print(df)

app = dash.Dash(__name__)

app.layout = Div([
    DataTable(
        columns=[
            dict(name='id', id='id', type='text'),
            dict(name='link', id='link', type='text', presentation='markdown'),
        ],
        data=df.to_dict('records')
    ),
])

app.run_server(debug=True)

2 Likes

@seferoezcan As the resize operation is expensive, the underlying Plotly.js library debounces the graph resize until no further resize request has been made for a short period of time. As such, a smooth transition will not resize the graph every step of the way but instead will wait for the transition to be completed before triggering the resize.

index.py

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go

from dash.dependencies import Input, Output, State, ClientsideFunction
from dash.exceptions import PreventUpdate

app = dash.Dash(__name__)
server = app.server

app.layout = html.Div(children=[
    html.Button(['Click to resize'], id='btn'),
    html.Div(id="transition-div",
        children=[
            dcc.Graph(
                responsive=True,
                style=dict(height='100%', width='100%'),
                figure={
                    'data': [{
                        'x': [1, 2, 3, 4],
                        'y': [5, 4, 3, 6],
                        'line': {'shape': 'spline'}
                    }],
                },
            )
        ]
    ),
])

@app.callback(
    Output('transition-div', 'className'),
    [Input('btn', 'n_clicks')]
)
def resize(n_clicks):
    if n_clicks is None:
        raise PreventUpdate

    return 'div-resize'


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

/assets/custom.css

#transition-div {
    height: 600px;
    padding: 10px;
    background-color: red;
}

#transition-div.div-resize {
    height: 1000px !important;
    transition: height 2s;
}

Hey,

yeah thats what my tests showed as well. Furthermore is there any update on the dcc.Loading compoent which seems to be broken since 1.7.0 and has seen multiple bug reports.

Hi,

Thank you for your reply. I’ve managed to get it working.
I’m quite new to dash and html and I was wondering if you could show me how to get a different name displayed instead of the url by reading from a different column of the same dataframe?
i,e, how would you edit the f(row) function to display more easily readable names for example:
google, dash, plotly, community, altavista, yahoo?

Hi,

I have managed to do it.

import dash

from dash_html_components import Div

from dash_table import DataTable

from pandas import DataFrame

def f(row): #Turns the dictionary d into the correct format for

return"[%s]({0})".format(row["url"]) %row["id"] #Where the "id" is the names of the links that will be seen

d = {

'id': ['Sky Tv', 'BBC', 'Amazon Video', 'Channel 4', 'ITV', 'Netflix'],

'url': [

    'https://tvplayer.com/',

    'https://www.bbc.co.uk/iplayer',

    'https://www.amazon.co.uk/Prime-Video/b?ie=UTF8&node=3280626031',

    'https://www.channel4.com/',

    'https://www.itv.com/hub/itv',

    'https://www.netflix.com/'

]

}

df = DataFrame(data=d)

df[“link”] = df.apply(f, axis=1)

app = dash.Dash(name)

app.layout = Div([

DataTable(

    columns=[

        dict(name='id', id='id', type='text'),

        dict(name='link', id='link', type='text', presentation='markdown'),

    ],

    data=df.to_dict('records')

),

])

app.run_server(debug=True)

is it possible to display an image (icon) using presentation=markdown and when image is clicked trigger a callback?

One important Dash-focused improvement to Plotly.js 1.52.0 which lands in this release of Dash is that click events on sunburst and treemap diagrams now fire in Dash even on non-leaf-nodes!

1 Like

Ah and also: we’ve made the sunburst and treemap branchvalues="total" calculation a little more tolerant of tiny discrepancies, so it should be a lot easier to make treemaps and sunburst charts once you upgrade to Dash 1.8.0 :tada:

1 Like

Moving from version 1.6.1 to 1.8.0 solved most of my responsiveness issues although I had to make some changes to some of the css hacks I was formerly using (parent container used to be display:flex but under 1.8.0 all the charts overflowed the container so I removed it). I posted my issue here: Problem with figure not updating dimensions when its parent container is resized and 1.8.0 solved most of that however the legend still needs a browser-resize/page refresh to not clash with the chart.

Very excited for this markdown function within dash table. Thanks for the great features.

However, I do find an interesting behavior when you use it in conjunction with dash_bootstrap_components.themes.BOOTSTRAP. The table turns out to have a margin that is negative and the table edges are cut off (see screenshot below).

I spent some time and found that there is an impact from .row class from dash_bootstrap_components.themes.BOOTSTRAP or a regular bootstrap css file. It gives a -15px to left margin and right margin. To fix this, you might need to override this .row class from css template. Hope this is helpful for other users face the same issue.

3 Likes

Can DataTable now support images in cells? alexcjohnson mentioned this feature was going to be supported in this release on this issue https://github.com/plotly/dash-table/issues/383. Its not clear to me how it can do that now

It can via the markdown presentation option.

Is there an example of this? I looked through https://dash.plotly.com/datatable and wasn’t able to find it. The only thing I see is this columns=[dict(name=‘a’, id=‘a’, type=‘text’, presentation=‘markdown’)]