XML not updating/saving in React Modeler Functional Component (React/TS)

I am trying to update/save the XML via the modeler.saveXML() function when the user updates the bpmn diagram but anytime I grab the xml it is always the original XML file I am using and never what xml equivalent if what is on the screen/user created. I feel like I have tried just about everything and am running out of ideas. I think it is because I have to create the modeler component in use effect, if I try to do it at the beginning of the react functional component the page has an error, so it always getting the original bpmnModeler component’s xml.

I have also tried using modeler.on() to detect a user change, which it does but then why I try to save the xml and look at it it is still the same. I have tried creating the modeler object in useState but it causes the app to crash when I do so.

Any help getting me going in the right direction would be greatly appreciated as I have been stuck on this for the past 3 days.

I have highlighted the more important parts. Here is my code:

const BpmnModelerComponent = () => {
    let modeler: any = null
    // const [modeler, setModeler] = useState(new BpmnModeler({
    //     container: '#bpmnview',
    //     keyboard: {
    //         bindTo: window
    //     }
    // }))

    const [xmlModalIsOpen, setXmlModalIsOpen] = useState(false);
    const [svgModalIsOpen, setSvgModalIsOpen] = useState(false)
    const [xmlText, setXmlText] = useState('')

    const openXmlModal = () => {

    const closeXmlModal = () => {

    const exportArtifacts = (modeler: any) => {
        console.log('xml saved')

    const openXMLPanel = (modeler: any) => {

    const saveModelerXml = async (modeler: any) => {
        try {
            const result = await modeler.saveXML();
            const { xml } = result;
          } catch (err) {

  **const getXml = (model: any) => {
        const { xml } = model
        console.log('xml = ' + xml)

    const setXml = (xml: string) => {

    const downloadXml = async (modeler: any, xml: string) => {

  **useEffect(() => {
        console.log('use effect')
        let newModeler = new BpmnModeler({
            container: '#bpmnview',
            keyboard: {
                bindTo: window

  useEffect(() => {
        modeler.on('commandStack.changed', () => {
            console.log('user changed something')
            // modeler.moddle.tomXML(modeler.definitions, { format: true }, function (err, updatedXML) {
            //     console.log('xml stuff')
            // })
            // modeler.saveXML({ format: true }, function(err, updatedXML) {
            //     console.log(updatedXML)
            // })
        }, [])

    const newBpmnDiagram = (modeler: any) => {
        openBpmnDiagram(modeler, emptyBpmn)

    const openBpmnDiagram = async (modeler: any, xml: any) => {
        try {
            const result = await modeler.importXML(xml);
            const { warnings } = result;
          } catch (err) {
            console.log(err.message, err.warnings);
            let canvas = modeler.get('canvas')

                <div id="bpmncontainer" style={{height: '80%'}}>
                    <div id="bpmnview" style={{ width: '100%', height: '120vh', float: 'left', overflowX: 'auto' }}></div>
                    <Button variant='outlined' style={buttonXML} onClick={() => {openXMLPanel(modeler)}}>XML</Button>
                    <Button variant='outlined' style={buttonSVG} >SVG</Button>
                    <Button variant='outlined' style={buttonSave} onClick={() => {saveModelerXml(modeler)}}>Save XML</Button>
                    <Box sx={style}>
                        <h3 style={{ position: 'absolute', color: 'black', alignContent: 'flex-start', top: '5%', left: '5%'}}>XML</h3>
                        <Typography id="modal-modal-description" sx={{ position: 'absolute', top: '10%', left: '5%', color: 'black', width: '100%' }}>
                        <Button variant='contained' style={downloadButtonXML} onClick={() => {downloadXml(modeler, xmlText)}}>Download XML</Button>
const setXml = (xml: string) => {


Note that setState in React is async. The new value for xmlText will be available on the next re-render of the Component. Try to log result from the saveXML call directly.

Here is an example of how we implemented debug mode, which prints the XML with each change:

1 Like

Wow thank you so much. That modeler.on function you posted actually fixed it. I tried that multiple times before I posted this too although the syntax was a little different so not exactly sure what changed.

For anyone who also has this problem I moved that modeler.on function back into useEffect where I am also instantiating the modeler object.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.