Dash: Rendering raw HTML

Created on 23 Aug 2017  路  6Comments  路  Source: plotly/dash

Thanks for Dash! :-D

I am trying to pass raw HTML through to Dash, such as HTML returned by calling pd.DataFrame.to_html() (as a shortcut to defining a function such as generate_table() in the getting started docs).

React seems to support this through a div that sets dangerouslySetInnerHTML. Passing this to html.Div raises an exception that the argument is not one of the 14 that are pre-defined.

Is there any way to do this with Dash?

Most helpful comment

@frogger72 - Good point. I ran into this myself on a personal project where I wanted to render HTML from a third-party source and converting it to the dash-html-components library would've been too complex.
I have created a dangeroulsySetInnerHTML component that you can use now https://github.com/plotly/dash-dangerously-set-inner-html. However, I recommend using the dash-html-components as much as possible.

All 6 comments

Thanks @edschofield ! It's not possible to render raw HTML right now (see https://github.com/plotly/dash/issues/44#issuecomment-311154651 for some more discussion).

I think that we'll ultimately solve this use case of DataFrame + Tables with a dedicated Table component that takes a dataframe as an input. I've started prototyping on this idea here: https://github.com/plotly/dash-table-experiments

Closing this for as I don't anticipate adding raw HTML support to Dash in the near future and the use case for tables in particular will be better solved through https://github.com/plotly/dash-table-experiments

Allowing dangerouslySetInnerHTML would be really useful for a lot of obscure cases where there is no predefined HTML component. For instance, I am trying to use embed and object to insert PDFs

@frogger72 - Good point. I ran into this myself on a personal project where I wanted to render HTML from a third-party source and converting it to the dash-html-components library would've been too complex.
I have created a dangeroulsySetInnerHTML component that you can use now https://github.com/plotly/dash-dangerously-set-inner-html. However, I recommend using the dash-html-components as much as possible.

Hello guys,
I stumbled on the same issue recently, I managed to solve it with Beautifulsoup and a recursive function

Parse your html with BeautifulSoup :

import bs4 as bs
html_parsed = bs.BeautifulSoup(html_snippet)

And use the following recursive function to convert the parsed html to a set of dash-html-components

import dash_html_components as html

def convert_html_to_dash(el,style = None):
    if type(el) == bs.element.NavigableString:
        return str(el)
    else:
        name = el.name
        style = extract_style(el) if style is None else style
        contents = [convert_html_to_dash(x) for x in el.contents]
        return getattr(html,name.title())(contents,style = style)

With the helper function to get a style dictionary from a list of style arguments of a Beautifulsoup element

def extract_style(el):
    return {k.strip():v.strip() for k,v in [x.split(": ") for x in el.attrs["style"].split(";")]}

This was a quick hack, but worked perfectly for what I wanted to do !

Your suggestion was very helpful. Thanks TheoLvs! I've changed some points for myself to use in callback to replace the contents of a DIV, and I'm sharing too. Thanks! Sorry for my english.

import bs4 as bs
import dash_html_components as html

def retorna_documento(numero):
    html_doc = '<b><i><u>Teste de texto</u></i></b><br><br><span style="background-color: #FFFF00">Documento n煤mero {}</span>'.format(numero)
    return convert_html_to_dash(html_doc)
def convert_html_to_dash(el,style = None):
    CST_PERMITIDOS =  {'div','span','a','hr','br','p','b','i','u','s','h1','h2','h3','h4','h5','h6','ol','ul','li',
                        'em','strong','cite','tt','pre','small','big','center','blockquote','address','font','img',
                        'table','tr','td','caption','th','textarea','option'}
    def __extract_style(el):
        if not el.attrs.get("style"):
            return None
        return {k.strip():v.strip() for k,v in [x.split(": ") for x in el.attrs["style"].split(";")]}

    if type(el) is str:
        return convert_html_to_dash(bs.BeautifulSoup(el,'html.parser'))
    if type(el) == bs.element.NavigableString:
        return str(el)
    else:
        name = el.name
        style = __extract_style(el) if style is None else style
        contents = [convert_html_to_dash(x) for x in el.contents]
        if name.title().lower() not in CST_PERMITIDOS:        
            return contents[0] if len(contents)==1 else html.Div(contents)
        return getattr(html,name.title())(contents,style = style)
Was this page helpful?
0 / 5 - 0 ratings