Skip to main content

Usage with React

important

Flowable Forms may not work as expected when used with React's Strict Mode. Strict Mode is a tool for highlighting potential problems in an application while developing, and while it helps in identifying unsafe lifecycle patterns, some third-party components may not be fully compatible with it. If you encounter issues or unexpected behavior, consider disabling Strict Mode for the part of the application that uses <Form>.

// Before: With Strict Mode
<React.StrictMode>
<Form />
</React.StrictMode>

// After: Without Strict Mode
<Form />

Form component

<Form> is the main React component of Flowable forms. It basically receives a form definition (config prop) and renders a form that matches it. The values in the form are stored into the payload, you can optionally pass a payload prop to the form with the initial values.

import {Form} from "@flowable/forms";
class App extends React.Component{
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onOutcomePressed=this.onOutcomePressed.bind(this);
}
onOutcomePressed(payload, outcome) {
console.log("OUTCOME PRESSED", payload, outcome);
}
onChange(payload) {
console.log("VALUE CHANGED", payload);
}
render() {
return (
<Form
config={frmDef}
onChange={this.onChange}
onOutcomePressed={this.onOutcomePressed}
payload={}
/>
);
}
}

Form properties

Props marked as *propName are mandatory.

NameTypeDescription
*config{rows: [{cols: [...]}]}12 column layout form definition
onChange(value: {$path: string, $value: any, $isOutcome: boolean}) => voidCallback function called whenever the payload is changed in the form
payload{ key: any}Payload object, if none is passed an empty object will be used
Components{ key: FormComponentClass }Additional components used by the form
langstringLanguage key used, e.g. "en_us".
See Localisation guide
translations{lang: {label1: "value1", label2: "value2", ...}}Object with key-value pairs associated to lang.
See Localisation guide
classNamestringClass name added to the topmost DOM element
outcomesElementElement or Element[]DOM elements where to render the outcome buttons
onOutcomePressed(payload: Payload, result: any) => voidThis callback will be called when an outcome button is pressed
fetch(url: string, options: RequestInit, onProgress?: function) => Promise<Response>Function used by the form to request data
additionalData{ key: any}Expressions in the form definition can use these values
enabledbooleanWhen enabled is false the form will be readonly
shadowDOMObject{}ShadowDOM enable and properties.
See Custom styles guide
forceValidationsbooleanWhen set to true, validations will be always shown.
onEvent(eventName: string, config: ResolvedColumn, state: {}) => booleanOptional event handler function.
See section Events for more information.
getFileTypes() => Promise<{key: string, title: string, formDefinitionKey: string}[]>Returns all the file types defined in your application. This prop will be of use inside upload component
getFormDefinition(formDefinitionKey: string) => Promise<FormLayout>Returns the form definition that corresponds to a form definition key. This prop will be of use inside upload component

Form methods

You can call these methods if you keep a reference to the Form object.
NOTE: For a safer way, please try to use methods through API from getApi().

NameParamsDescription
uploadFiles(payload: Payload,
autoupload?: boolean
) => void
Searches for files in the payload not already uploaded and uploads them
isValid() => booleanReturns true when there are no failing validations, and false in other cases
getPayload() => PayloadReturns the current values binded to the form
setPayload($path: string, $value: Payload) => voidSets ($path, $value) into payload
getAdditionalData() => {}Returns object with current additionalData
getLang() => stringReturns the current lang
setLang(lang: string) => voidSets lang string as current lang
getApi() => {}Returns object with API methods
See section API for more information.

Use key and loading state to prevent errors

If your application is using react you need to be careful with the component initiallisation and the react reconciliation mechanism.

In the initiallisation process flowable-forms has to do several things like setting the default values in the payload and initialising the state of internal components described in the form definition.

Say you have an app with a list of items in the left sidebar and a <Form> in the main area. When you click an item in the sidebar the <Form> has to render the item with its form definition. With the naive implementation you would have:

<Form 
payload={this.state.selectedItem.payload}
config={this.getFormDefinitionRestService(this.state.selectedItem.formKey)}/>

This will render the form perfectly for the first selected item. But for the second one we may see strange behaviours:

  • The same <Form> component will be used because the react reconciliation.
  • The payload is already there so the form will be rendered with the old form definition and the new payload while the new form definition is being loaded.
  • If the form definition of the 2 items is the same, the <Form> doesn't know it has to do the initiallisation again so it won't set the default values.
  • If the form definition of the old and the new items are the same or similar, the internal components will be reused. While this should be ok most times, some things could be already initiallised.

As a general rule to solve this issues your app needs to set a different key to the <Form> every time it represents a different item and it must not render the form until every prop is loaded.

For example:

{!this.state.isLoading && <Form 
key={this.state.selectedItem.id}
payload={this.state.selectedItem.payload}
config={this.state.formDefinition}/>}