LSPS documentation logo
LSPS Documentation
Form Design

A form is designed in the forms definition using the Forms editor. It comprises constructors, methods, local variable and a tree of form components, such as, input fields, radio lists, etc. To design the component tree, you insert the required form components into a canvas and define the properties of components in the Properties view.

On runtime, the form is resolved into a tree of components with the components based on the components in the definition: one component in the definition can result in multiple components in the form on runtime, for example, when you use a repeater, the component in the repeater results in multiple runtime components. Each component on runtime can be attached only to one parent: a component needs to be detached for its current parent before you can attach a component to another parent.

phrasesForm.png
A forms::form definition with a Form
The form is instantiated by a User Task or a Document based on its UI Definition property. The property holds the constructor call that the task or document use to create their form. The constructor calls the createWidget() method, which does the following:

  1. It calls the preCreateWidget() method as defined by the user is executed.
  2. It creates the root component of the form tree, FormWidget.
  3. It constructs the tree of form components as defined in the form definition.
  4. It calls the Init expressions defined on the components of the tree.
  5. It calls the postCreateWidget() method as defined by the user is executed.

Then form is then rendered.

The constructor call can be parametric so you can send input to your form when it is instantiated.

The FormWidget component cannot be changed; however, you can access it with the getWidget() method.

When the user interacts with the form, components of the tree produce event objects. These events trigger listener expressions: When an event occurs, its listener expression is performed; for example, when the user clicks a button, a ClickEvent is produced, and the Click Listener expression of the button is executed; when the user inserts a value, a ValueChangeEvent is produced, and the expression defined as the OnChangeEventListener of the component is executed.

The component tree can grow as the user works with the form since components can be added to the tree dynamically; for example, a new popup can be created every time the user clicks a button. To prevent storing of unnecessarily large trees, the server calls the garbage collector over the form: The collector prunes the component tree branches that are not referenced. The collector is called when the form is submitted or saved.

Important: The example forms in this guide often work with data stored in variables. In production, such solutions are not intended for storage of extensive data amount and might result in out-of-memory errors. When acquiring data for forms use queries whenever the data is persisted in a database.

Defining a Parametric Constructor

To define a constructor for your Form, open the methods file of your Form and define the constructor as a new constructor method.

An example parametric constructor: The initialDate variable is defined as the form's local variable.

DateField {
     public DateField(Date date) {
     initialDate := date;
  }
}
parametricConstructorCall.png
Calling a parametric form constructor from a document

Defining a Local Form Variable

To define a local form variable, do the following:

  1. Make sure you have the form resource opened in the Form editor.
  2. In the Outline view, right-click the form and go to New > Variable.
  3. In the displayed Properties view, define the variable properties.
  4. In the methods file of your Form, define the constructor that will initialize the value of the variables if applicable.
localvarinitconstructor.png
Parameterized form constructor that sets a local variable value

Creating a Form Hierarchy

Important: Note that since both, the ui and forms implementations, can be used to return a UIDefinition to a Document or To-do; sometimes it can be unclear on runtime which implementation is used; typically if you use an expression that returns human::UIDefinition. The LSPS Server might not be able to detect which implementation you are using and return an exception. Therefore make sure to remove either the ui or the forms module form your module imports so the used implementation can be recognized correctly based on the imported module.

To create the component hierarchy in your form definition, do the following:

  1. Open the form definition file (double-click it in the GO-BPMN Explorer).
  2. Click the required component in the palette and then click to the respective position on the canvas. Alternatively right-click the position in the canvas, go to Insert Component and select the component from the context menu.

    insertingComponent.png
    Inserting a component into the form from the context menu
  3. Define the component properties in the Properties view on the Details tab; if you require other properties, such as, style properties and additional size properties, call the respective methods on your component on the Init tab as an expression.

    definingInit.png
    Init expression on a poopup component
    This method can be used to reuse a Form.

Inserting a Parent Component

You can select one or multiple form Components and wrap them with another components in the Form graphical editor.

To insert such a parent form component over another component, do the following:

  1. In the Form editor, right-click the component.
  2. In the context menu, go to Insert Parent and select the component to use as the wrapper component.
wrappingComponent.png
Wrapping component in a layout component

Deleting a Parent Component

To delete only the parent component and preserve its child components, right-click the parent component and click Shift Children Up.

Note that the option is only available if the children can be accommodated in the form after the deletion; for example, it is not possible to delete a Vertical Layout with multiple child components if it has a Panel component as its parent.

Searching for Form Components

If an error on a form component occurs during runtime, the server returns an error message with the modeling ID of the form component. While the modeling id is generated automatically, you can change it with setModelingId(). To get the modeling id of a component, call the getModelingId() method.

To search for the form component that caused the error in the current workspace, do the following:

  1. Go to Search > Find Form Component.
  2. In the displayed search dialog, enter the ID.

Displaying Form Source Code

Since forms as well as their components are defined as Records with methods, you can display the entire Form source in the Expression editor:

  1. In the Form editor, right-click any form component.
  2. On the context menu, select Display Form Expression.

Enabling Error Reporting on Components

To enable reporting of runtime errors so that they contain modeling IDs of involved components, run your server with the -Dcom.whitestein.lsps.vaadin.ui.debug=true system property:

  • If you are running PDS Embedded Server, go to Server Connection -> Server Connection Settings, select the connection and click Edit.
    settingServerProps.png
    Enabling modeling IDs on form components
  • If you are connecting to another PDS server or you are using SDK Embedded Server, switch to Java perspective; go to Run > Run Configurations; select the configuration under Java Application or Remote Java Application and add the property on the Arguments tab to VM arguments.
    settingServerPropsSdk.png

Troubleshooting a Form

When troubleshooting a form, consider the following:

  • Examine the form expression: right-click the form in the form editor and select Display Widget Expression.
  • Add breakpoints to expressions in the form and run it in LSPS Debugger.