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?
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)
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-componentslibrary 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-componentsas much as possible.