Most of the examples I have seen rely on building the entire HTML front end via the python interface. Is there a way to use a pre-defined HTML5 template and substitute the graphs in there?
This way one can prototype the interface independently of the dash logic.
Since Plotly dash is built on flask, any chance jinja2 templating will be
in the works?
On Sun, Jun 25, 2017 at 11:59 PM Zafarali Ahmed notifications@github.com
wrote:
Most of the examples I have seen rely on building the entire HTML front
end via the python interface. Is there a way to use a pre-defined HTML5
template and substitute the graphs in there?This way one can prototype the interface independently of the dash logic.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/plotly/dash/issues/44, or mute the thread
https://github.com/notifications/unsubscribe-auth/AF1yH8Nbtf1nOwkXmyHkKPkKitQBZIzrks5sHyyegaJpZM4OE2k0
.>
Cedric Yau
[email protected]
There isn't any plan to do this right now. While the dash_html_components components render themselves directly as html components, the dash_core_components components can't be rendered with just HTML tags (unless we switched them to web components). This limits the extent to which a Dash app could be mocked up entirely in HTML.
Writing web markup with Python classes may seem pretty odd at first, but there are actually a lot of really great things that you can do it with it:
app.layout template in Dash and then re-use it in the rest of your projects or share it with your team members (since it's just Python code)This way one can prototype the interface independently of the dash logic.
The "logic" of a Dash app is separated from the initial "view" of the app already. The app's app.layout property defines what the app looks like, and the app.callbacks define the logic of the app, or how the app responds to changes.
Closing this for now since it's not on the immediate roadmap, but certainly always happy to hear more thoughts or feedback :)
Another note - one could also write a Dash component that takes a raw HTML string and renders it with React's dangerouslySetInnerHTML. It could look something like:
RawHTML('''
<table>
[...]
</table>
''')
and then if you wanted Jinja templating, you could run your string through Jinja before passing into the component, like:
RawHTML(Jinja.render('''
<table>
[...]
</table>
'''))
Here's how to create custom components in Dash: https://plot.ly/dash/plugins.
I would argue its extremely useful to be able to generate HTML using other means than just dash_html_components. I'm personally not a fan of templates such as Jinja, but I do love the dominate library. Its syntax is concise and the use of with keyword makes your code much more elegant and readable than the current approach of dash_html_components. If I had to design something similar to Dash from scratch, I would certainly try to build on top of dominate (basically just extend it to allow plugging in dash_core_components and other things).
Apart from these aesthetic considerations, dash_html_components enforces some unreasonable restrictions on the allowed set of HTML element attributes, This does not make sense in a modern web front-end development where almost every fancy library requires you to set some custom HTML attributes. The only way I can get around it is by adding the attributes using javascript on the client side... I do not see the point in these restrictions. That's great that Dash allows you to do a lot with just Python, but I don't see why it should restrict you if you want to do more with 3rd party client-side libraries,
TL;DR I do think it should be possible to plug in HTML code generated elsewhere into Dash. Seamless support for dominate would be awesome, but even just the RawHTML suggested above is good enough because it'll get the job done.
one alternative might be to ditch dash for just flask and plotly (which are core components of dash anyway) and build on top of that. back in the days @chriddyp showed us how it's done here.
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 DangerouslySetInnerHTML 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.
I still stand by the belief that dash-html-components is a great way to render complex HTML as you are writing code in Python. This automatically provides us with:
For example, conditional formatting a table to create a component like

is trivial (see https://community.plot.ly/t/coloured-text-in-a-table-conditional-formatting/7112/8?u=chriddyp)
Further, you can easily re-use components that you have created since it's just regular Python!
dash_html_componentsenforces some unreasonable restrictions on the allowed set of HTML element attributes,
As far as I'm aware, this is just related to Dash not currently supporting data-* and aria-* attributes. This is more of a bug than a limitation, and it will be supported in the future.
@chriddyp, if I understand you correctly, what you say about Reusable, portable components and Nice argument validation refers mostly to dash_core_components (especially the former), i.e. Python wrappers for React components. And this is of course really valuable and is basically the reason I use Dash,
My point, however, is that writing plain HTML is way too verbose with dash_html_components. In my view, both Jinja2 and dominate library provide more elegant way to template your HTML code. Dash is great for simple MI (Tableau-like) tasks, but as soon as you need something more complex it starts getting in your way.
Imagine a complex web app where you'd like to use a few Plotly graphs here and there. And suppose you want the cross-filtering on those graphs, which is a breeze with Dash. But because the graphs are scattered over distant parts of your HTML DOM, it forces you to implement the whole DOM structure via dash_html_components (whereas what you really want is to simply inject a few Dash Core Components in various places of you web app). Another example is where you have two unrelated pieces on the same page which are most easily implemented with Dash, but again, these pieces are located in completely different parts of DOM. And no, iframe is not a good solution to this. It is not even a feasible solution in the first case, and is a very poor solution to the second one. SEO considerations aside, I often want to interact with Dash part of my web app from outside (i.e. from plain javascript), and I want to do it directly without the need for postMessage etc.
I'm not too familiar with React, but let me summarize why I think dash_html_components exist:
1) We need to have a single top-level React component (in Dash front-end)
2) It is nice to have the ability to modify any part of your HTML markup through Dash Python callbacks/React,
After brief googling I came across the project aknuds1/html-to-react which seems like it could be solution to this problem. I can imagine the following workflow (I'm going to use Jinja2 as an example, but this would allow us to create HTML markup any way we like, including e.g. dominate):
1) I write a Jinja2 template which is a mixture regular Flask HTML templating and dash_core_components. Where a Dash Core Component gets injected into the HTML the following happens:
a) It returns simple div with a unique id, such as <div id='dash-core-component-wldjakle'>
b) The actual Dash Component (which is what is currently being returned) is simply stored somewhere in Dash application instance.
As a result, the layout is no longer a hierarchy of Components, but rather a plain HTML string.
2) When the response is sent back to Dash front-end, it contains the following:
a) The string with layout HTML which we discussed above
b) All Components which we have stored in Dash application, serialized to JSON - this is similar to what the current rendering method returns, but instead of creating a large nested object, it would just be a list of components.
3) The following would happen on the front-end:
a) HTML string gets parsed with aknuds1/html-to-react library (it's easy to convert it from a Node module to plain javascript with e.g. Browserify or Webpack). It creates React DOM structure.
b) All Dash Core Components can be injected into this DOM structure by replacing their placeholder divs (which can be identified by unique ids).
Unless I'm missing something, as a result of this we'd get the same React DOM structure as we currently do. We satisfy both initial requirements - we still have just one top-level React component, and all plain HTML elements are part of React system, so could be easily interacted with from Dash Python callbacks.
Only other thing I can think of which is currently done on Python side is validation of all component ids between registered callbacks and layout. While no longer possible to do on the Python side (unless you parse HTML to DOM with e.g. lxml parser, which is also easy enough), it could be easily done on front-end side once html is converted to React DOM.
I've described what happens with initial layout, but the exact same thing could be applied to Dash callbacks which return children for some element.
With this approach you no longer need dash_html_components at all, so one less thing to maintain. If you want to generate DOM in Python, just use dominate - it's more elegant, flexible and very mature/robust. If you want to preserve backwards compatibility you could keep dash_html_components interface and just make it use dominate underneath (which should be extremely trivial).
Finally, not related to the above - for those who are happy to use dash_html_components, it would still be really handy if they supported with syntax similar to dominate - it would make the code much more compact, elegant and readable.
I wrote something to address this very same concern:
https://github.com/masdeseiscaracteres/dash-html-template
It is just a proof-of-concept that could benefit a lot from the ideas above. My original idea was to be able to inject Dash components into Jinja templates but I ended up specifying my own sort of "templating format".
I totally agree with @nirvana-msu. Yes, we do have dash-html-components, which is pretty handy at creating html components. But what about html structure? As far as I can see, most of the show and tell projects are merely "stacks" of html components. How do we control the structure of our application? In the layout page of your tutorial, I can only find out a layout that is controlled by style={'columnCount': 2}. What if we need more than this?
On my current project, I want to add bootstrap support for the application. This is the part of the code for a corner of the page:
html.Div(className='content', children=[
html.Div(className='container-fluid', children=[
html.Div(className='row', children=[
html.Div(className='col-lg-3 col-md-6 col-sm-6', children=[
html.Div(className='card card-stats', children=[
html.Div(className='card-header',
**{'data-background-color': 'orange'},
children=[
html.I(className='fa fa-file-alt')
]),
html.Div(className='card-body', children=[
html.Div(style={'font-family':'Roboto','font-weight':'bold'},
children=[
html.H3(className='title', children=[
html.B('Textual Analysis')],
)
]),
html.Hr(),
html.Div(className='alert alert-info alert-with-icon',
**{'data-notify': 'container'},
children=[
html.I(className='fa fa-check-square',
**{'data-notify': 'icon'}),
html.Button(className='close',
**{'data-dismiss':'alert',
'aria-label':'Close'},
type='button',
children=[
html.I('close', className='material-icons')
]),
html.Span(**{'data-notify':'message'},
children=[
html.B('Check to select all items')],
),
],
),
html.Div(className='col-lg-3 col-md-6 col-sm-6',
style={'background-color': 'yellow'},
children=[
html.H4(className='card-title', children=[
html.I(className='fa fa-hospital fa-w-14 fa-1x grape5',
**{'data-notify': 'icon'}),
'Facilities'
])
]),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': 'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
multi=True,
value='MTL'
)
])
])
])
])
])
])
I am new to this, maybe I am on the wrong track, but I don't know how else I can do it.
Same problem, When we want a full fledged application. We need a lot of html.
Here's my attempt at turning an HTML-like language with embedded Python into calls to Dash constructors: https://github.com/jkseppan/htexpr/
With that you can write @ssword's example like this:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from htexpr import compile
app = dash.Dash(__name__, external_stylesheets=[
'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'
], external_scripts=[
'https://code.jquery.com/jquery-3.3.1.slim.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js'
])
app.layout = compile("""
<div class='content'>
<div class='container-fluid'>
<div class='row'>
<div class='col-lg-3 col-md-6 col-sm-6'>
<div class='card card-stats'>
<div class='card-header' data-background-color='orange'>
<i class='fa fa-file-alt' />
</div>
<div class='card-body'>
<div style={'font-family':'Roboto','font-weight':'bold'}>
<h3 class='title'><b>Textual Analysis</b></h3>
<hr />
<div class='alert alert-info alert-with-icon' data-notify='container'>
<i class='fa fa-check-square' data-notify='icon' />
<button class='close'
data-dismiss='alert'
aria-label='Close'
type='button'>
<i class='material-icons'>close</i>
</button>
<span data-notify='message'>
<b>Check to select all items</b>
</span>
</div>
<div class='col-lg-3 col-md-6 col-sm-6' style={'background-color': 'yellow'}>
<h4 class='card-title'>
<i class='fa fa-hospital fa-w-14 fa-1x grape5' data-notify='icon' />
Facilities
</h4>
</div>
<Dropdown
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': 'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
]
multi={True}
value='MTL' />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
""").run()
if __name__ == '__main__':
app.run_server(debug=True)
This is almost HTML, but you have to close all tags (but <hr /> is recognized), attributes can take Python values, and you can embed Python code. It gets compiled into a sequence of calls to Dash constructor functions (html.Div(className='content', children=[html.Div(...)])).
Forum post: https://community.plot.ly/t/htexpr-write-dash-layouts-in-html-syntax/21669
Great work @jkseppan, really helpful for me since writing HTML is much faster for me.
Most helpful comment
@chriddyp, if I understand you correctly, what you say about
Reusable, portable componentsandNice argument validationrefers mostly todash_core_components(especially the former), i.e. Python wrappers for React components. And this is of course really valuable and is basically the reason I use Dash,My point, however, is that writing plain HTML is way too verbose with
dash_html_components. In my view, bothJinja2anddominatelibrary provide more elegant way to template your HTML code. Dash is great for simple MI (Tableau-like) tasks, but as soon as you need something more complex it starts getting in your way.Imagine a complex web app where you'd like to use a few
Plotlygraphs here and there. And suppose you want the cross-filtering on those graphs, which is a breeze with Dash. But because the graphs are scattered over distant parts of your HTML DOM, it forces you to implement the whole DOM structure viadash_html_components(whereas what you really want is to simply inject a few Dash Core Components in various places of you web app). Another example is where you have two unrelated pieces on the same page which are most easily implemented with Dash, but again, these pieces are located in completely different parts of DOM. And no,iframeis not a good solution to this. It is not even a feasible solution in the first case, and is a very poor solution to the second one. SEO considerations aside, I often want to interact with Dash part of my web app from outside (i.e. from plain javascript), and I want to do it directly without the need forpostMessageetc.I'm not too familiar with React, but let me summarize why I think
dash_html_componentsexist:1) We need to have a single top-level React component (in Dash front-end)
2) It is nice to have the ability to modify any part of your HTML markup through Dash Python callbacks/React,
After brief googling I came across the project aknuds1/html-to-react which seems like it could be solution to this problem. I can imagine the following workflow (I'm going to use
Jinja2as an example, but this would allow us to create HTML markup any way we like, including e.g.dominate):1) I write a
Jinja2template which is a mixture regular Flask HTML templating anddash_core_components. Where a Dash Core Component gets injected into the HTML the following happens:a) It returns simple div with a unique id, such as
<div id='dash-core-component-wldjakle'>b) The actual Dash Component (which is what is currently being returned) is simply stored somewhere in Dash application instance.
As a result, the
layoutis no longer a hierarchy of Components, but rather a plain HTML string.2) When the response is sent back to Dash front-end, it contains the following:
a) The string with layout HTML which we discussed above
b) All Components which we have stored in Dash application, serialized to JSON - this is similar to what the current rendering method returns, but instead of creating a large nested object, it would just be a list of components.
3) The following would happen on the front-end:
a) HTML string gets parsed with aknuds1/html-to-react library (it's easy to convert it from a Node module to plain javascript with e.g. Browserify or Webpack). It creates React DOM structure.
b) All Dash Core Components can be injected into this DOM structure by replacing their placeholder divs (which can be identified by unique ids).
Unless I'm missing something, as a result of this we'd get the same React DOM structure as we currently do. We satisfy both initial requirements - we still have just one top-level React component, and all plain HTML elements are part of React system, so could be easily interacted with from Dash Python callbacks.
Only other thing I can think of which is currently done on Python side is validation of all component ids between registered callbacks and layout. While no longer possible to do on the Python side (unless you parse HTML to DOM with e.g.
lxmlparser, which is also easy enough), it could be easily done on front-end side once html is converted to React DOM.I've described what happens with initial layout, but the exact same thing could be applied to Dash callbacks which return
childrenfor some element.With this approach you no longer need
dash_html_componentsat all, so one less thing to maintain. If you want to generate DOM in Python, just usedominate- it's more elegant, flexible and very mature/robust. If you want to preserve backwards compatibility you could keepdash_html_componentsinterface and just make it usedominateunderneath (which should be extremely trivial).Finally, not related to the above - for those who are happy to use
dash_html_components, it would still be really handy if they supportedwithsyntax similar todominate- it would make the code much more compact, elegant and readable.