Useservice('modeling') returning cannot read properties of undefined (reading 'context') camunda modeler

I am trying to add a custom tab in property tab in camunda modeler, as I bundle the plugin and run the app i get the following error :

useservice(‘modeling’) cannot read properties of undefined (reading ‘context’) camunda modeler

The error seems to come from SpellProps.js file :
contents of the file. :
import { html } from ‘htm/preact’;

import { TextFieldEntry, isTextFieldEntryEdited } from ‘@bpmn-io/properties-panel’;
import { useService } from ‘bpmn-js-properties-panel’;

export default function(element) {

return [
{
id: ‘spell’,
element,
component: Spell,
isEdited: isTextFieldEntryEdited
}
];
}

function Spell(props) {
const { element, id } = props;

const modeling = useService(‘modeling’);
const translate = useService(‘translate’);
const debounce = useService(‘debounceInput’);

const getValue = () => {
return element.businessObject.spell || ‘’;
};

const setValue = value => {
return modeling.updateProperties(element, {
spell: value
});
};

return html<${TextFieldEntry} id=${ id } element=${ element } description=${ translate('Apply a black magic spell') } label=${ translate('Spell') } getValue=${ getValue } setValue=${ setValue } debounce=${ debounce } tooltip=${ translate('Check available spells in the spellbook.') } />;
}

Error stack trace attached as image

Github : bpmn-js-examples/properties-panel-extension at main · bpmn-io/bpmn-js-examples · GitHub

The example you linked works as intended for me. If you made any changes, please share the project with us where the issue is reproduceable

Hey Martin, thanks for getting back, the application works in a standalone fashion but when i bundle it as a plugin and use in the camunda modeler application then its failing with above error.

U can clone this repo : GitHub - naveinn/property-panel-extension

and try to bundle it and insert it as plugin in camunda modeler main repo : GitHub - camunda/camunda-modeler: An integrated modeling solution for BPMN, DMN and Forms based on bpmn.io.

When bundeling for the Camunda Modeler, you include a second version of the properties panel an preact in your bundle. This causes a mismatch between the instances used in the modeler. As preact expects only one global instance, this will cause some errors.

Please try the version exposed via camunda-modeler-plugin-helpers

Hey Martin, I am not able to exactly spot the place where I include second version of the properties panel, I have included

presets: ['@babel/preset-env', '@babel/preset-react']

in my webpack.config file, is this what you are referring to ?
it would be great if u can point the place were the change has to be made, git review comments are appreciated

thanks again for getting back…

Hey, the problem is the bundeling. This is a bit weird, I’ll try to explain:

In SpellProps.js, you import from bpmn-js-properties-panel and others. This is fine when you build a standalone app, as your bundler (rollup) will deduplicate the dependencies for you. You only end up with one Properties Panel instance, even if other libraries also import it.

However, the Camunda Modeler is already bundled and includes a version of the properties panel in it. When you then bundle your plugin, you will end up with 2 versions of the Properties panel - one in the modeler bundle and one in the plugin.

To allow you to still create plugins, the modeler exposes the property panel instances with a helper. So instead of importing from bpmn-js-properties-panel, you can try importing from camunda-modeler-plugin-helpers/vendor/bpmn-js-properties-panel. This exposes the properties panel instance bundled within the modeler, so we do not end up with 2 versions.

I hope this clears it up a bit :slight_smile:

Wohoo… u made my day, the solution works like a pro.
Also I have an additional question here, I went through the plugin docs, bpmn-properties panel has a set of compenents by itself like textfield entry and selectentry and so on…

But in my usecase i want to add a dialog box, which isn’t a component that bpmn provides, so to achieve this can i use react ?

I have a bad experience using react with bpmn as its not able to run the modeler as it throws the following error : Custom Prop for Service Tasks: `TypeError Cannot add property __, object is not extensible`

So i went ahead with preact apporach which again requires external css import, but that again causes me the problem as raised here : Unable to import CSS into bpmn property panel - #3 by Martin

So can u give me the more cleaner way or approach to add custom react components or preact with css onto this plugin approach ?

1 Like

Lets say if i want to use material ui components for my application, is that possible ?

I tried the following

import { TextFieldEntry, isTextFieldEntryEdited } from 'camunda-modeler-plugin-helpers/vendor/@bpmn-io/properties-panel';
import { is } from 'bpmn-js/lib/util/ModelUtil';

import { html } from 'htm/preact';
import { debounce } from 'min-dash';

import { useService } from 'camunda-modeler-plugin-helpers/vendor/bpmn-js-properties-panel';
import { React } from 'camunda-modeler-plugin-helpers/react';
import { Button } from '@mui/material';

import { Modal } from 'camunda-modeler-plugin-helpers/components'; 
import CustomButton from '../../customComponents/CustomButton';




export default function(element, modeling, translate, injector) {
  
  return [
    {
      id: 'spell',
      element,
      modeling:modeling,
      translate:translate,
      injector:injector,
      component: Spell
      
    }
  ];
}




function Spell(props) {


  //const {useService} = yourModuleName;
  //const translateCopy = useService('translate');
  //console.log(useService)
  const { element, id, modeling, translate, injector} = props;

  const translateFun = injector.get('translate')
  const modelingFun = injector.get('modeling')
  //console.log(modeling)
  const modeling1 = useService('modeling');
  //const translate = useService('translate');
  //const debounce = useService('debounceInput');

  const getValue = () => {
    return element.businessObject.spell || '';
  };

  const setValue = (value) => {
    console.log(modelingFun)
    return modelingFun.updateProperties(element, {
      spell: value
    });
  };

  const handleButtonClick = () => {
    window.alert('Button clicked!');
  };

  

  //console.log(id,element,translate,getValue,setValue,debounce)

 

  return html`
    <${TextFieldEntry}
      id=${id}
      element=${element}
      description=${translate('Apply a black magic spell')}
      label=${translate('Spell')}
      getValue=${getValue}
      setValue=${setValue}
      debounce=${debounce}
      tooltip=${translate('Check available spells in the spellbook.')}
    />

    <${CustomButton} 
    />

    <${Button} 
    />
  `;
}


But it fails with below error :
Uncaught (in promise) DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('[object Object]') is not a valid name.

I am not 100% sure on this, but I think material UI component library will depend on “normal” react, not the exposed one from the modeler. With webpack, it worked for me with this config:

  resolve: {
    alias: {
      'react': 'camunda-modeler-plugin-helpers/react',
    }
  },

I am sure there are plugins for rollup to achieve this as well.

As the properties panel expects a Preact component rather than React, you can try to change the resolution to Preact, but I am not sure if this will work.

I’ll check if you can wrap a React component in a way that Preact accepts it if I have time later.

1 Like

I tried the same that doesn’t seem to work its expecting react during bundling
I can see this preact material ui as one alternative : Button

but yeah even I am still working on how to use react components, let me know if u have any leads