Integrating draw.io diagram (mxgraph) in Dash

Hi!

I am trying to embed a https://draw.io digram in Dash. The diagram can be exported to be embedded in HTML as this:

<div class="mxgraph" style="max-width:100%;border:1px solid transparent;" data-mxgraph="{&quot;highlight&quot;:&quot;#0000ff&quot;,&quot;nav&quot;:true,&quot;resize&quot;:true,&quot;toolbar&quot;:&quot;zoom layers lightbox&quot;,&quot;edit&quot;:&quot;_blank&quot;,&quot;xml&quot;:&quot;&lt;mxfile host=\&quot;app.diagrams.net\&quot; modified=\&quot;2021-03-25T11:05:48.472Z\&quot; agent=\&quot;5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36\&quot; etag=\&quot;umQOHWFOX7TgyuBoHaM_\&quot; version=\&quot;14.5.1\&quot;&gt;&lt;diagram id=\&quot;IUjv3nLa85AREJ93xwhi\&quot; name=\&quot;Page-1\&quot;&gt;jZJNb4MwDIZ/DcdJCRGlu46162UnDhynlLgkUiAoDQP26xeGw4eqSjvFefwR57UjltXDh+Wt/DQCdBQTMUTsPYpjekhe/TGRcSbpMZlBZZXAoBXk6gcQEqSdEnDfBTpjtFPtHpamaaB0O8atNf0+7Gb0/tWWV/AA8pLrR1oo4eRMjwlZ+QVUJcPLlKCn5iEYwV1yYfoNYqeIZdYYN1v1kIGexAu6zHnnJ96lMQuN+09CUVya8XobU1Vl5Eop++rSF6zyzXWHH8Zm3RgUsKZrBExFSMTeeqkc5C0vJ2/vZ+6ZdLX2N+pNLAfWwfC0T7r83q8NmBqcHX0IJrADCoYbw1K896v+NIgqN9qHPI4jr5bSqyreQGHCdR3An2+zxuz0Cw==&lt;/diagram&gt;&lt;/mxfile&gt;&quot;}"></div>
<script type="text/javascript" src="https://viewer.diagrams.net/js/viewer-static.min.js"></script>

In dash, I tried the following code and I am getting the same rendered HTML, but the diagram is not loading, any idea how to debug or solve this issue? Thanks.

html.Div(
    ['Loading ...'],
    className='mxgraph',
    style={"maxWidth": "100%", "border": "1px solid transparent"},
    **{'data-mxgraph': "{&quot;highlight ...... &gt;&quot;}"},
),
html.Script(type="text/javascript", src='https://viewer.diagrams.net/js/viewer-static.min.js'),

Hi @zapzap40 did you by any chance fix this, as this would be a nice integration?

Yes, that is possible. You just need to delay the JS loading appropriately. Here is a small example,

import dash
import dash_html_components as html
import dash_defer_js_import as dji

app = dash.Dash(__name__)
app.layout = html.Div([
    html.Div(className='mxgraph', style={"maxWidth": "100%", "border": "1px solid transparent"},
             **{'data-mxgraph': "..."}),
    dji.Import(src='https://viewer.diagrams.net/js/viewer-static.min.js')
])

if __name__ == '__main__':
    app.run_server()
3 Likes

Hi @Emil thanks for the answer, do you perhaps have an example with data-mxgraph filled out, the reason I ask is because I am getting the following error:

JSON.parse: expected property name or '}' at line 1 column 2 of the JSON data

with a simple square:

data-mxgraph="{&quot;highlight&quot;:&quot;#0000ff&quot;,&quot;nav&quot;:true,&quot;resize&quot;:true,&quot;toolbar&quot;:&quot;zoom layers lightbox&quot;,&quot;edit&quot;:&quot;_blank&quot;,&quot;xml&quot;:&quot;&lt;mxfile host=\&quot;app.diagrams.net\&quot; modified=\&quot;2021-06-07T06:06:13.695Z\&quot; agent=\&quot;5.0 (Windows)\&quot; etag=\&quot;4lPJKNab0_B4ArwMh0-7\&quot; version=\&quot;14.7.6\&quot;&gt;&lt;diagram id=\&quot;YgMnHLNxFGq_Sfquzsd6\&quot; name=\&quot;Page-1\&quot;&gt;jZJNT4QwEIZ/DUcToOriVVw1JruJcjDxYho60iaFIaUs4K+3yJSPbDbZSzN95qPTdyZgadm/GF7LAwrQQRyKPmBPQRzvktidIxgmwB4IFEaJCUULyNQvEAyJtkpAswm0iNqqegtzrCrI7YZxY7Dbhv2g3r5a8wLOQJZzfU4/lbByoslduPBXUIX0L0cheUrugwk0kgvsVojtA5YaRDtZZZ+CHrXzukx5zxe8c2MGKntNgknk8bs8fsj3+KtuDhxP+HZDVU5ct/RhatYOXgGDbSVgLBIG7LGTykJW83z0dm7kjklbaneLnEnlwFjoL/YZzb93WwNYgjWDC6EEdkuC0cZEO7p3i/6RF1WutL8nxmnkxVx6UcUZJIy/LgP49622mO3/AA==&lt;/diagram&gt;&lt;/mxfile&gt;&quot;}"

Lol I have tried for 5 hours, I give up. There are just so many quote types, what should one do if there is " quotes then ’ quotes then " quotes.

**{'data-mxgraph': '{"highlight":"#0000ff","nav":"true","resize":"true","toolbar":"zoom layers lightbox","edit":"_blank","xml":"&lt;mxfile host=\"app.diagrams.net\" modified=\"2021-06-07T06:06:13.695Z\" agent=\"5.0 (Windows)\" etag=\"4lPJKNab0_B4ArwMh0-7\" version=\"14.7.6\"&gt;&lt;diagram id=\"YgMnHLNxFGq_Sfquzsd6\" name=\"Page-1\"&gt;jZJNT4QwEIZ/DUcToOriVVw1JruJcjDxYho60iaFIaUs4K+3yJSPbDbZSzN95qPTdyZgadm/GF7LAwrQQRyKPmBPQRzvktidIxgmwB4IFEaJCUULyNQvEAyJtkpAswm0iNqqegtzrCrI7YZxY7Dbhv2g3r5a8wLOQJZzfU4/lbByoslduPBXUIX0L0cheUrugwk0kgvsVojtA5YaRDtZZZ+CHrXzukx5zxe8c2MGKntNgknk8bs8fsj3+KtuDhxP+HZDVU5ct/RhatYOXgGDbSVgLBIG7LGTykJW83z0dm7kjklbaneLnEnlwFjoL/YZzb93WwNYgjWDC6EEdkuC0cZEO7p3i/6RF1WutL8nxmnkxVx6UcUZJIy/LgP49622mO3/AA==&lt;/diagram&gt;&lt;/mxfile&gt;"}'},

Sure. I think you forgot to escape the html string that you copied. Here is a simple square with html escaping included as part of the script (to ease copying from draw.io),

import dash
import dash_html_components as html
import dash_defer_js_import as dji
from html import unescape

mxgraph = r'{&quot;highlight&quot;:&quot;#0000ff&quot;,&quot;nav&quot;:true,&quot;resize&quot;:true,&quot;toolbar&quot;:&quot;zoom layers lightbox&quot;,&quot;edit&quot;:&quot;_blank&quot;,&quot;xml&quot;:&quot;&lt;mxfile host=\&quot;app.diagrams.net\&quot; modified=\&quot;2021-06-07T06:06:13.695Z\&quot; agent=\&quot;5.0 (Windows)\&quot; etag=\&quot;4lPJKNab0_B4ArwMh0-7\&quot; version=\&quot;14.7.6\&quot;&gt;&lt;diagram id=\&quot;YgMnHLNxFGq_Sfquzsd6\&quot; name=\&quot;Page-1\&quot;&gt;jZJNT4QwEIZ/DUcToOriVVw1JruJcjDxYho60iaFIaUs4K+3yJSPbDbZSzN95qPTdyZgadm/GF7LAwrQQRyKPmBPQRzvktidIxgmwB4IFEaJCUULyNQvEAyJtkpAswm0iNqqegtzrCrI7YZxY7Dbhv2g3r5a8wLOQJZzfU4/lbByoslduPBXUIX0L0cheUrugwk0kgvsVojtA5YaRDtZZZ+CHrXzukx5zxe8c2MGKntNgknk8bs8fsj3+KtuDhxP+HZDVU5ct/RhatYOXgGDbSVgLBIG7LGTykJW83z0dm7kjklbaneLnEnlwFjoL/YZzb93WwNYgjWDC6EEdkuC0cZEO7p3i/6RF1WutL8nxmnkxVx6UcUZJIy/LgP49622mO3/AA==&lt;/diagram&gt;&lt;/mxfile&gt;&quot;}'
app = dash.Dash(__name__)
app.layout = html.Div([
    html.Div(className='mxgraph', style={"maxWidth": "100%"}, **{'data-mxgraph': unescape(mxgraph)}),
    dji.Import(src='https://viewer.diagrams.net/js/viewer-static.min.js')
])

if __name__ == '__main__':
    app.run_server()
2 Likes

Wow, how did I miss this! Really cool solution. Thanks for resurfacing @Emil and @Abeserra for authoring and @zoohair for maintaining :slightly_smiling_face:

1 Like