Linting and Properties Panel

Hi,
Can the linting module display error which occur in the properties panel (such as missing field value) as an error on the according element in the model? And also display this error inside the tooltip with the errors which are shown based on the linting rules?

I think the Camunda Modeler Desktop application does this but I have no clue how it works. Would you mind explining how to marry the field validations inside the properties panel and the linting module? Both for custom groups/fields and for groups which are already included in the camunda properties panel.

Any tips and guidance would be awesome. Thank you! :slight_smile:

Camunda Modeler does it via camunda/linting.

Have a look around and feel to ask more specific follow up questions. :slight_smile:

Hey,

Thank you for the reply. I have been trying to set it up but i cannot get it to run with the modeler. Is there a working example anywhere? It is very confusing which packages work with what.

I want to embed the camunda modeler in a web project which is bundled with vite and I am using these packages:

import BpmnModeler from ‘camunda-bpmn-js/lib/camunda-platform/Modeler’;
import lintingModule from ‘@camunda/linting/modeler’;
import ‘@camunda/linting/assets/linting.css’;

const Modeler = () => {
    const modeler = useModelerContext();
    const modelerContainerRef = useRef<HTMLDivElement>(null);
    const modelerPropertiesPanelRef = useRef<HTMLDivElement>(null);
    const styles = useStyles();

    useEffect(() => {
        modeler.attachTo(modelerContainerRef.current!);
        const propertiesPanel = modeler.get<any>('propertiesPanel');
        propertiesPanel.attachTo(modelerPropertiesPanelRef.current!);

        modeler
            .createDiagram()
            .then(
                () => {
                    modeler.get<any>('canvas').zoom('fit-viewport');
                    // return;
                    // modeler.get<any>('linting').activate();
                    return modeler
                        .saveXML({format: true})
                        .then(
                            xmlResult => {
                                console.log(xmlResult);
                                return;
                                const linter = new Linter({
                                    modeler: 'web', // `desktop` or `web` modeler, defaults to `desktop`
                                    type: 'platform' // `cloud` or `platform` diagrams, defaults to `cloud`
                                });
                                return linter
                                    // .lint(xmlResult.xml)
                                    // modeler:executionPlatform="camunda-platform" modeler:executionPlatformVersion="7.24"
                                    // xmlns:stepgen="http://example.com/stepgen"
                                    .lint(`
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL bpmn0.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" 
modeler:executionPlatform="camunda-platform" modeler:executionPlatformVersion="7.24">
  <bpmn:process id="Process_1" isExecutable="false" name="Mein Entwurf">
    <bpmn:startEvent id="StartEvent_1" name="Startereignis"/>
  </bpmn:process>
</bpmn:definitions>
                                        `)
                                    .then(
                                        lintResult => {
                                            console.log('### lint', lintResult);
                                            modeler.get<any>('linting').setErrors(lintResult);
                                        }
                                    );
                                console.log(modeler.get<any>('linting'));
                            }
                        );
                }
            ).catch(console.error);

        return () => {
            propertiesPanel.detach();
            modeler.detach();
        };
    }, [modeler]);

    return (
        <div className={styles.root}>
            <div className={styles.modeler} ref={modelerContainerRef} />
            <div
                className={styles.modelerPropPanel}
                ref={modelerPropertiesPanelRef}
            />
        </div>
    );
};

It would be easier if you shared a CodeSandbox with your minimal implementation, so that we can see what goes wrong.

I found this working example for custom linting:
https://codesandbox.io/p/sandbox/bpmn-custom-lint-c9u6lm

Could you please explain what needs to be done in order to swap the custom linting for camunda/linting and swap the modeler for the camuna modeler (‘camunda-bpmn-js/lib/camunda-platform/Modeler’) with this configuration:

    executionPlatform: {
        name: 'Camunda Platform',
        version: '7.24'
    },

I also inspected the code of the properties panel and its fields. The onValidate function does not fire any events and only sets local errors. How does the linter get access to these local errors and displays them on the canvas?

Thank you very much!

Communication between linting and properties panel happens via the eventBus, cf. my answer to a similar question: Properties panel error badge is not showing - #2 by jarekdanielak

Could you please explain what needs to be done in order to swap the custom linting for camunda/linting and swap the modeler for the camuna modeler

We believe the documentation on our project is enough to get you started. We are happy to answer specific, self-contained questions in the forum, but you need to do your homework. :wink: