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.
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.
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,
};