Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering raw HTML #118

Closed
edschofield opened this issue Aug 23, 2017 · 6 comments
Closed

Rendering raw HTML #118

edschofield opened this issue Aug 23, 2017 · 6 comments

Comments

@edschofield
Copy link

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?

@chriddyp
Copy link
Member

Thanks @edschofield ! It's not possible to render raw HTML right now (see #44 (comment) 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

@chriddyp
Copy link
Member

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

@ghost
Copy link

ghost commented Sep 22, 2017

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

@chriddyp
Copy link
Member

chriddyp commented Dec 7, 2017

@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.

@TheoLvs
Copy link

TheoLvs commented Jan 10, 2018

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 !

@luizanisio
Copy link

luizanisio commented Dec 21, 2018

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)

byronz pushed a commit that referenced this issue Apr 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants