Skip to main content

Implement custom form events in Flowable Work

Target audience: Developers

Introduction

There are some scenarios where out-of-the-box forms components are not enough to fulfill certain needs. In those scenarios it might be useful to add custom event handling for your components. For example, you might want certain fields to react when another field value changes.

In the next sample we will show how to configure our form in a way that a list of values are reset to empty when one of the form fields changes.

The form

For our example we have created a simple form with three text fields, the requirement is that when the first of them changes, then the other two needs to be set to empty. As you might know already, technically, changing a field to empty it's the same than forcing its payload value to empty.

Form

In order to configure our custom dependency mapping for the fields, we will need the id of the first element which is text1 and the value binding for the dependant fields: text2 and text3.

The Flowable Work customisation

For exposing our custom logic to Work, there is an optional property called onFormsEvent within the externals module. This object matches the same type than the one described in the forms event handler section.

const dataToCleanMapping = {
text1: ["text2", "text3"],
};

const onFormsEvent = (eventName, column, state, api) => {
if (eventName === "my-custom-event") {
const valuesToClean = dataToCleanMapping[state.id];
for (var i = 0; i < valuesToClean.length; i++) {
api.payload.set(valuesToClean[i], undefined);
}
}
return true;
};

As you can see in the code above, the dataToCleanMapping variable is a simple key-value mapping where the key is the id of the field and the value is an array of payload values to set to empty.

Our logic to clear values is only executed when the my-custom-event event has been previously triggered, then we look for matching values in the dataToCleanMapping based on the state.id property.

In the next section we will see how to trigger the my-custom-event event.

Triggering a custom event

In order to use a custom event, we need a custom component to trigger this. The component that will trigger the event is exactly the same text component provided by the forms library, so what we do is overriding the product component with our own implementation:

import { ComponentStore, Model } from "@flowable/forms";

class CustomText extends Model.FormComponent {
render() {
const Text = this.props.Components.originalText;
return (
<Text
{...this.props}
onChange={(target) => {
this.props.onChange(target);
if (dataToCleanMapping[this.props.config.id]) {
this.props.onEvent("my-custom-event", this.props.config, {
id: this.props.config.id,
});
}
}}
/>
);
}
}

export const CustomTextComponent = ["text", CustomText];
export const ProductTextComponent = ["originalText", ComponentStore.text];

As you can see, the render method uses the Text component and we handle the onChange event, triggering the custom event and passing the component id.

info

In the onChange handler, we check that the component id is part of the dataToCleanMapping configuration, this way we avoid that every single Text component in the form triggers this event.

Probably you realised that the out-of-the-box Text component has been renamed to originalText. The reason behind this, it's to break an endless loop that would happen if the custom component uses its own render method.

Finally, the externals module should look like the next:

export default {
formComponents: [CustomTextComponent, ProductTextComponent],
onFormsEvent,
};

The result

Result