I'm creating a React component which will render a graph by using an XML string with mxGraph. The graph is rendering inside the component, but some shapes, such as circles, diamonds, and swimlanes, are not rendering correctly; they appear as simple squares or rectangles instead. This is particularly odd since some non-rectangular shapes (such as Documentation) appear correctly.
The graph is created using an edited version of jgraph's "grapheditor" tool with some customized shapes:
This grapheditor tool is identical to the reference implementation, with only the addGeneralPalette() function changed in Sidebar.js
to use our customized shapes:
/**
* Adds the general palette to the sidebar.
*/
Sidebar.prototype.addGeneralPalette = function(expand)
{
var fns = [
this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;', 80, 80, 'Start', 'Start', null, null, 'start begin starting beginning'),
this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;', 200, 120, 'Process', 'Process', null, null, 'process proc'),
this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;', 200, 120, 'Template', 'Template', null, null, 'template temp'),
this.createVertexTemplateEntry('rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;', 200, 120, 'Decision', 'Decision', null, null, 'decision decide'),
this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;', 200, 120, 'Documentation', 'Documentation', null, null, 'documentation doc internal'),
this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;', 280, 40, 'Action', 'Action', null, null, 'action'),
this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ffb74d;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#fff3e0;fillColor=#FFFFFF;', 200, 120, 'Sub-Process', 'Sub-Process', null, null, 'subprocess sub-process sub'),
this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;', 80, 80, 'End', 'End', null, null, 'end ending conclusion resolution close'),
this.createVertexTemplateEntry('swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;', 1020, 200, 'Phase', 'Swimlane', null, null, 'swimlane organizer phase flow stage')
];
this.addPaletteFunctions('general', mxResources.get('general'), (expand != null) ? expand : true, fns);
};
And editing the File > Save As function in EditorUi.js
to print the graph's XML to the console so we can use it elsewhere:
/**
* Saves the current graph under the given filename.
*/
EditorUi.prototype.save = function(name)
{
if (name != null){
if (this.editor.graph.isEditing()){
this.editor.graph.stopEditing();
}
var xml = mxUtils.getXml(this.editor.getGraphXml());
try{
if (xml.length < MAX_REQUEST_SIZE){
//Print XML to console
console.log('The graph can be imported to mxGraph using the following XML: ');
console.log(xml);
}else{
mxUtils.alert(mxResources.get('drawingTooLarge'));
mxUtils.popup(xml);
return;
}
this.editor.setModified(false);
this.editor.setFilename(name);
this.updateDocumentTitle();
}catch (e){
this.editor.setStatus(mxUtils.htmlEntities(mxResources.get('errorSavingFile')));
}
}
};
Exporting this graph from the grapheditor tool results in the following XML string:
<mxGraphModel dx="1572" dy="832" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="21" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="560" width="1020" height="200" as="geometry"/></mxCell><mxCell id="20" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="340" width="1020" height="220" as="geometry"/></mxCell><mxCell id="19" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="20" width="1020" height="320" as="geometry"/></mxCell><mxCell id="9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Start" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;" vertex="1" parent="1"><mxGeometry x="220" y="30" width="80" height="80" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="Process" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;" vertex="1" parent="1"><mxGeometry x="160" y="200" width="200" height="120" as="geometry"/></mxCell><mxCell id="17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="8"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint y="730"/><mxPoint x="630" y="730"/></Array></mxGeometry></mxCell><mxCell id="4" value="Template" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="-100" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="7"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="6"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="4"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="Decision" style="rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;" vertex="1" parent="1"><mxGeometry x="170" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="6" value="Action" style="rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="145" y="630" width="280" height="40" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="7" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="7" value="Documentation" style="shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;" vertex="1" parent="1"><mxGeometry x="470" y="360" width="200" height="120" as="geometry"/></mxCell><mxCell id="8" value="End" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;" vertex="1" parent="1"><mxGeometry x="590" y="610" width="80" height="80" as="geometry"/></mxCell></root></mxGraphModel>
Now, in my React application (wholly separate from the grapheditor tool, which is a standalone web application that doesn't interact with my React application), I take this XML string and use mxGraph to decode and render it in a React component:
import React, { Component } from "react";
//We imported mxClient et al via <script> tags in index.html
let mxGraph = window.mxGraph;
let mxUtils = window.mxUtils;
let mxEvent = window.mxEvent;
let mxRubberband = window.mxRubberband;
let mxKeyHandler = window.mxKeyHandler;
let mxCellHighlight = window.mxCellHighlight;
let mxCodec = window.mxCodec;
class App extends Component {
componentDidMount(){
var graph = new mxGraph(document.getElementById('divGraph'));
var rubberband = new mxRubberband(graph);
var keyHandler = new mxKeyHandler(graph);
var highlight = new mxCellHighlight(graph, '#999999', 10);
let xmlString = '<mxGraphModel dx="1572" dy="832" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="21" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="560" width="1020" height="200" as="geometry"/></mxCell><mxCell id="20" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="340" width="1020" height="220" as="geometry"/></mxCell><mxCell id="19" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="20" width="1020" height="320" as="geometry"/></mxCell><mxCell id="9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Start" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;" vertex="1" parent="1"><mxGeometry x="220" y="30" width="80" height="80" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="Process" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;" vertex="1" parent="1"><mxGeometry x="160" y="200" width="200" height="120" as="geometry"/></mxCell><mxCell id="17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="8"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint y="730"/><mxPoint x="630" y="730"/></Array></mxGeometry></mxCell><mxCell id="4" value="Template" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="-100" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="7"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="6"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="4"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="Decision" style="rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;" vertex="1" parent="1"><mxGeometry x="170" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="6" value="Action" style="rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="145" y="630" width="280" height="40" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="7" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="7" value="Documentation" style="shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;" vertex="1" parent="1"><mxGeometry x="470" y="360" width="200" height="120" as="geometry"/></mxCell><mxCell id="8" value="End" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;" vertex="1" parent="1"><mxGeometry x="590" y="610" width="80" height="80" as="geometry"/></mxCell></root></mxGraphModel>';
var doc = mxUtils.parseXml(xmlString);
var codec = new mxCodec(doc);
codec.decode(doc.documentElement, graph.getModel());
graph.fit();
graph.setPanning(true);
graph.setEnabled(false);
graph.setHtmlLabels(true);
//graph will listen for click events
graph.addListener(mxEvent.CLICK, (sender, event) => {
let cell = event.getProperty('cell');
if(cell != null){
//highlight the clicked cell
highlight.highlight(graph.view.getState(cell));
}
});
}
render() {
return (
<div>
<div id="divGraph"></div>
</div>
)
}
}
export default App;
This React application uses the following index.html
which imports the various mxGraph libraries from a local directory:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<script type="text/javascript">mxBasePath = './mx/src'</script>
<script type="text/javascript" src="./mx/src/js/mxClient.js"></script>
<script type="text/javascript" src="./mx/Init.js"></script>
<script type="text/javascript" src="./mx/EditorUi.js"></script>
<script type="text/javascript" src="./mx/Editor.js"></script>
<script type="text/javascript" src="./mx/Sidebar.js"></script>
<script type="text/javascript" src="./mx/Graph.js"></script>
<script type="text/javascript" src="./mx/Format.js"></script>
<script type="text/javascript" src="./mx/Shapes.js"></script>
<script type="text/javascript" src="./mx/Actions.js"></script>
<script type="text/javascript" src="./mx/Menus.js"></script>
<script type="text/javascript" src="./mx/Toolbar.js"></script>
<script type="text/javascript" src="./mx/Dialogs.js"></script>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
Unfortunately, when the application renders the graph, it appears like this:
I'm not entirely sure what to attribute this problem to, as I believe I've imported all of the requisite libraries such as Shapes.js
and such. I've checked the mxGraph documentation and this thread about a similar issue, but importing Shapes.js as recommended in that thread did not seem to solve the issue (or I may be importing Shapes.js incorrectly).
Any insight on how to approach this problem is greatly appreciated.
It turns out the issue was due to the palette we created in the grapheditor's Sidebar.js file. The shapes which were not rendering correctly needed "shape=" appended to the beginning of their style string, like so:
this.createVertexTemplateEntry('shape=ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;', 80, 80, 'Start', 'Start', null, null, 'start begin starting beginning'),
this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;', 200, 120, 'Process', 'Process', null, null, 'process proc'),
this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;', 200, 120, 'Template', 'Template', null, null, 'template temp'),
this.createVertexTemplateEntry('shape=rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;', 200, 120, 'Decision', 'Decision', null, null, 'decision decide'),
this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;', 200, 120, 'Documentation', 'Documentation', null, null, 'documentation doc internal'),
this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;', 280, 40, 'Action', 'Action', null, null, 'action'),
this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ffb74d;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#fff3e0;fillColor=#FFFFFF;', 200, 120, 'Sub-Process', 'Sub-Process', null, null, 'subprocess sub-process sub'),
this.createVertexTemplateEntry('shape=ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;', 80, 80, 'End', 'End', null, null, 'end ending conclusion resolution close'),
this.createVertexTemplateEntry('shape=swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;', 1020, 200, 'Phase', 'Swimlane', null, null, 'swimlane organizer phase flow stage')
Making this change to the grapheditor tool resulted in proper XML being exported, which, when imported to the React component via mxGraph, rendered correctly.