LSPS documentation logo
LSPS Documentation
Input Components

Input components serve to acquire input from the user. Depending on their type, they hold a certain value, which is stored in their binding; for example, an input field holds a string, so the binding must be able to hold a string value.

When the user enters an input or when they change the focus of the cursor, depending on whether the component is immediate, the component checks if the input value is correct; for example, whether the value in a Decimal Field contains a number. If the value is incorrect, the field is marked as invalid and no further processing takes place. If the value is correct the binding value is updated and the component produces a value-change event, ValueChangeEvent: when the event is produced, the closures defined by the change listeners of the component are executed (see Performing Action on Input in an Input Component).

Common Properties and Functionalities

  • Binding: the relevant value and target slot; for a Text Field, binding represents the displayed and stored value; for Tree Table this is the currently selected node, etc.
  • Required: if checked, the component is marked with the * symbol to indicate that the user must enter a value into the component; no validation logic is provided.
  • Immediate: if the changes on the components are to be produced immediately or on focus change
  • Validation: you can add validation rules for the input values with the addValidator() call

Getting the User Input from an Input Component

To get the value as entered by the user, that is, even if it is not valid, call getUserText(). The return value is always a String.

Note: To acquire the value in the target object of the binding that is the most recent valid value, use getValue().

Performing Action on Input in an Input Component

An input component produces a value change event when its input value changes. When the event is produced, the following is performed:

  • The action defined by the setOnChangeListener() method
  • The action defined by the setOnValidValue() method if the value of the component is valid, that is, none of the validators (inferred, explicitly added, or validator of the format) returns a message (isValid() returns true); it is basically a shorthand for
    if myComponent.isValid() then
    ...
    end

Example

c.setNumberFormat("#km");
c.setOnValidValue({ e ->
  def String userText := c.getUserText();
  userText := userText.replaceAll("km", "");
  metersField.setValue(userText.toDecimal()*1000);
});

If you need to work with previous values of an input component, you can acquire these from the oldValue property of the ValueChangeEvent.

c.setOnChangeListener({e:ValueChangeEvent-> oldValue.setValue(e.oldValue);
newValue.setValue(c.getValue())})

Input Components Reference

Input components hold a value and allow the user to enter a value: when this happens, the components executes the action defined by its value change listener. The input values are stored in the target object defined by their binding.

Text Components

Text components, that is, Text Field, Text Area and Password Field, allow the user to enter free-text input with the following additional options:

  • restriction of the number of characters using the setMaxLength() methods The user will not be able to enter an input longer than the set limit.
    c.setMaxLength(20)
  • display a hint in the component before the user enters their input using the setHint() method
    c.setHint("Enter your notes here.");
  • automatically expand the area vertically to wrap the input text with the setExpandable(true) method call

Text Field (forms::TextField)

The Text Field component ( ) is rendered as a single-line text field that allows entering text input.

Important: The caption of the Text Field is rendered by the parent layout component. Hence if you create a form with a sole Text Field component, the form will be rendered without its caption text. This is due to limits of the Vaadin framework.

TextFieldForm.png
Form with a Text Field
Expression that returns a TextField:

textField := new forms::TextField("Text Field Caption", new forms::ReferenceBinding(&varString));
textField.setValue("Binding value in the reference string object");
textField.setMaxLength(10);
textField
TextFieldRendered.png
Text Field rendered in the default theme

Text Area (forms::TextArea)

The Text Area component ( ) is rendered as a multi-line free-text field. It is expandable by default: its length adapts to accommodate user input.

If you want to set the height, that is, the number of lines in the text area:

  • If the Text Area is expandable (by default), use setMaxRows() and setMinRows().
  • If the Text Area is not expandable, use the setRows(Integer rows) method.
TextAreaForm.png
Form with a Text Area

Important: The caption of the Text Field is rendered by the parent layout component. Hence if you create a form with a sole Text Area component, the form will be rendered without its caption text. This is due to limits of the Vaadin framework.

Expression that returns a Text Area

myTextArea.setHeight("4")
TextAreaRendered.png
Text area rendered

Rich Text Area (forms::RichTextArea)

The Rich Text Area component ( ) enables the user to enter formatted text. You can also set the area to hold a formatted text from your form: use HTML formatting:

MyRichText.setValue("i <b> am <font color=""blue""> <i>rich </i> </font> </b> <font color=""blue""> <u>text</u> </font>")
richTextAreaRendered.png

Password Field (forms::PasswordField)

The Password Field component ( ) is a single-line text field that hides the input.

When implementing password fields the component only prevents the displaying of the input. To secure the provided data, make sure the form uses the HTTPS protocol.

PasswordFieldForm.png
Form with a Password Field

Important: The caption of the Password Field is rendered by the parent layout component. Hence if you create a form with a sole Password Field component, the form will be rendered without its caption text. This is due to limits of the Vaadin framework.

Expression that returns a Password Field

def PasswordField p := new PasswordField("Password:", &password);
p.focus();
p.isRequired();
p
PasswordFieldRendered.png
Password Fields rendered

Decimal Field (forms::DecimalField)

The Decimal Field component ( ) is rendered as a single-line field that allows the user to enter a decimal value. The format of the decimal value is by default set to user's locale: You can refine the allowed format with the setNumberFormat method.

Important: The caption of the field is rendered by the parent layout component. Hence if you create a form with a sole Text Field component, the form will be rendered without its caption text. This is due to limits of the Vaadin framework.

DecimalFieldForm.png
Form with a Decimal Field
Expression that returns a DecimalField

new forms::DecimalField("Value", &varValue);
DecimalFieldRendered.png
Decimal Field rendered in the default theme
DecimalFieldInvalid.png
Decimal Field with an invalid value

Defining Decimal Format

To define the format of the decimal value in a Decimal Field, use setNumberFormat():

def forms::DecimalField df := new forms::DecimalField("Value", &value);
df.setNumberFormat("#,##0.00;(#,##0.00)");
df.setOnChangeListener({
   changeevent ->
      def Integer rounded := roundUp((df.getValue() as Decimal));
      value := rounded;
      df.setValue(rounded)
    }
);

Date Field and Local Date Field

The Date Field and Local Date Field components are rendered as a single-line text field that allows the user to enter a date either using the calendar picker or by typing the date in one of the allowed date formats.

DateFieldForm.png
Form with a Text Field
Expression that returns a Date Field

def Date meetingTime :=  now();
def DateField myDateField := new DateField("Meeting", &meetingTime);
myDateField.setDateFormat("yyyy-MM-dd' at 'HH:mm:ss z");
myDateField.addValidator(
  {
    dv:Date -> if (dv > date(2016,3,3))
    then 
      null
    else
      "The meeting must occur later than March 2, 2016."
    end
  }
);
myDateField

Expression that returns a Local Date Field

def LocalDate meetingTime :=  now().toLocalDate();
def LocalDateField myLocalDateField := new LocalDateField("Meeting", &meetingTime);
myLocalDateField.setDateFormat("yyyy-MM-dd");
myLocalDateField.addValidator(
  {
    ldv:LocalDate -> if (ldv > date(2016,3,3).toLocalDate())
    then
      null
    else
      "meeting too soon"
    end
  }
);
myLocalDateField
DateFieldRendered.png
Date field with the default date format and with the date picker expanded

Defining Allowed Date Format on a Date Field and Local Date Field

To define the format of the date the user can enter into the Date Field or Local Date Field, call setDateFormat() or setDateFormats. The format parameter is defined as a String with the possible values of the java SimpleDateFormat (refer to http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html).

To use the date format of the LSPS Application, set the format either to date to use the dateFormat or to dateTimeFormat to use the default date-and-time format via the LspsAppConnector.getApplicationMessage().

To set the error message displayed when the entered date does not match the required format with the method setParseErrorMessage().

Check Box (forms::CheckBox)

The Check Box component ( ) is a simple check box with Boolean Binding: its caption renders next to the check box.

CheckBoxForm.png
Form with a Check Box
Expression that returns a CheckBox

new forms::CheckBox("I agree", &varAgree)
CheckBoxRendered.png
Check Box rendered in the default theme
The Check Box component produces the ValueChangeEvent when its check box is selected or unselected: to handle such a change, add a Change Listener to the component.

Example Change Listener on a Check Box component

confirmationCheck.setOnChangeListener(
   { e ->
      if confirmationCheck.getValue() = true
        then c.setEnabled(true)
      end
    }
)

Select Components

The Select components provide the user options which they can select and include such component as combo box, radio button list, etc.

Removing the No-Value Option in Select Components

By default, the select components contain an option with no value the user can select: to disable this no-value option, call setNullSelectionAllowed(false) on the component.

Setting the Select Options

You can define the options available in a select component either in the Properties view or with the component methods:

  • The options defined in the Options property of the component are loaded when the form is loaded.
    • Map: map of values and labels; for example, map(findAll(Region), { region:Region -> region.name })
    • Objects: collection of objects

      The labels are calculated by calling the toString() function over the objects, for example, findAll(Region).

    • Select items: collection of options defined as SelectItem objects; for example,
      collect(findAll(Region),
      { r:Region -> new SelectItem(value -> r, label -> r.name)}
      )
  • The options set with the setOptionsDataSouce() or setOptions() method load the options from anywhere in the form and you can load it at the moment when the component is created. Options loaded in this way are lazy-loaded: they are loaded at the moment they are displayed.

    Setting options with method calls

    //various calls that set the options in a combo box:
    myCombo.setOptionsDataSource(new TypeDataSource(User), new PropertyPathValueProvider(User.name));
    myCombo.setOptions(allValues, new IdentityValueProvider(String));
    myCombo.setOptions({ 1, 2, 3 })

Important: If you set the options of a component in both ways, that is, using the Options property and the setOptionsDataSouce() or setOptions() call, the one called later takes precedence: to identify the order of the method calls, right-click the form, select Display Widget Expression, and examine the code.

Combo Components

Combo Box (forms::ComboBox)

The Combo Box component ( ) renders as a single-line text field with a drop-down list of options: The user can select one option in the drop-down menu.

Options can be defined as a Map or a Collection, or an OptionsDataSource. To define an action when the user selects or unselects an option, use the setOnChangeListener() method.

Search Combo Box (forms::SearchComboBox)

The Search Combo Box component ( ) renders as a single-line text field with a drop-down list of options: The user can select one option in the drop-down menu and the options are filtered out once the user has entered the minimum amount of characters (3 by default).

The value set in the filter is passed as a SubstringFilter to the Options data source: if you are using a custom data source, make sure that the data source processes the filter value correctly.

//Example getData() method of a custom data source (record implements forms::DataSource):
  public List<Object> getData(Integer startIndex*, Integer count*, Collection<forms::Filter> filters, Set<Sort> sortSpecs){
     if filters.isEmpty() then
        getAll(startIndex, count)
     else
        //value in the filter:
        def String currentFilter := cast(filters[0], SubstringFilter).value;
        getMyDataFromMyDS(currentFilter)
     end
  }

Options can be defined as a Map or a Collection of objects or SelectItems, or an OptionsDataSource.

To define an action when the user selects an option, use the setOnChangeListener() method.

In addition, you can set the following:

  • minimum number of characters for the search filter to apply with the setMinimalFilterLength() method
  • number of options displayed in the drop-down with the setPageLength() method
  • time to wait after user input before searching for applicable options with the setFilterTimeout() method
SearchComboBoxRendered.png

Support for Entering a Custom Value

To allow the user to enter a value that is not available in the options in a combo box component, use the setNewItemHandler() method.

c.setNewItemHandler(
   {
     newValue:String ->
     newValue
   }
)

Note that the closure has void as return value, the user will not be able to enter a custom value:

c.setNewItemHandler(
   {
     newValue:String ->
     //The closure returns void so the user will be able to enter only one the option values:
     debugLog({ -> "User entered a new value: " + newValue}, INFO_LEVEL);
   }
)

If you enable this feature on a combo component, typically you will need to add the new option to the options of the combo component: use the setOptions() method to implement this behavior. Also, if you working with options that are persisted while new options are not persisted, consider defining the ValueProvider parameter: ValueProvider defines how to display the options and that possibly including your new option. For example, you could handle a new option as follows:

c.setNewItemHandler(
   {
     newValue:String ->
     options := add(options, new SelectItem(label -> newValue, value -> newValue));
     c.setOptions(options);
     //the value returned when you request value of the combo component:
     newValue
   }
);

To modify the added options, you can preprocess the options in the setOptions() method with a value provider:

c.setNewItemHandler(
   {
     newValue:String ->
     options := add(options, new SelectItem(label -> newValue, value -> newValue));
     c.setOptions(options, new ClosureValueProvider({ newOption:String -> newOption}));
     //the value returned when you request value of the combo component:
     newValue
   }
);

Multi-Select Combo Box (forms::MultiSelectComboBox)

The Multi-Select Combo Box component ( ) renders as a single-line text field with a drop-down list of options. The user can select multiple options in the drop-down menu.

Options can be defined as a Map or a Collection, or an OptionsDataSource. To define an action when the user selects or unselects a combo box option, use the setOnChangeListener() method.

MultiSelectComboBoxRendered.png

Single-Select List (forms::SingleSelectList)

The Single-Select List component ( ) displays a list of options from which the user can select one option. You can set a limit to the number of displayed options using setRowCount(Integer): if more options are available that the set limit, the list of options becomes scrollable.

To define the action performed when select or unselect of an item, use the setOnChangeListener() method.

SingleSelectListRendered.png
Single Select List with an option selected
Example expression that returns a single select list

def String selectedValue;
def SingleSelectList singleSelect := new SingleSelectList("My Single Select", &selectedValue);
singleSelect.setOptions([ "value" -> "displayed key", "another value" -> "another displayed value" ]);
singleSelect.setOnChangeListener( {_ -> myText.setValue(singleSelect.getValue())});
singleSelect.setRowsCount(2);
singleSelect.setNullSelectionAllowed(false);
singleSelect;

Multi-Select List (forms::MultiSelectList)

The Multi-Select List component ( ) displays a list of options from which the user can select multiple options.

It can define the number of displayed Options using setRow(Integer): if more options are available that the set limit, the list of options becomes scrollable.

To define an action when the user selects or unselects an item, use the setOnChangeListener() method.

Example expression that returns a multi select list

def MultiSelectList msl:= new MultiSelectList("", &selectedItems);
msl.setOptions([ "value1" -> "displayed option 1", "value2" -> "displayed option 2"]);
msl.setOnChangeListener( { _-> selection.refresh() });
msl.setNullSelectionAllowed(false);
msl.setRows(2);
msl;

Check Box List (forms::CheckBoxList)

The Check Box List ( ) component is a form component that displays a list of options with check boxes and allows the user to select multiple options using the check boxes. To define an action when the user selects or unselects an option in the list, use the setOnChangeListener() method.

Example expression that returns a check box list

def CheckBoxList cbl:= new CheckBoxList("", &selectedItems);
cbl.setOptions([ "value1" -> "displayed option 1", "value2" -> "displayed option 2"]);
cbl.setOnChangeListener( { _-> selection.refresh() });
cbl.setNullSelectionAllowed(true);
cbl;

Radio Button List (forms::RadioButtonList)

The Radio Button List component ( ) is a form component that displays a list of options and allows the user to select exactly one option by clicking a radio button. To define an action when the user selects or unselects an option in the list, use the setOnChangeListener() method.

Example expression that returns a radio button list

def RadioButtonList rbl:= new RadioButtonList("");
rbl.setOptions([ "value1" -> "displayed option 1", "value2" -> "displayed option 2"]);
rbl.setBinding(&selectedItem);
rbl.setOnChangeListener( { _-> select.refresh() });
rbl.setNullSelectionAllowed(true);
rbl;
radioButtonListRendered.png

Token Field (forms::TokenField)

The Token Field component ( ) serves for selection of multiple options. It is rendered as a combo box by default with the options displayed based on users input in its drop-down box: the component searches for the options with labels that contain the entered characters. The user then selects the option by clicking the proposed option or entering the entire values and hitting Enter. They can remove the selected option by clicking the X icon in the option. Whenever the user selects or removes an option, the component fires a ValueChangeEvent.

The component is rendered by default as a combo box, so the user can click the arrow on the combo box to display the options. However, you can render the Token Field as a Text Field by calling its addStyleName("tokentextfield") method.

By default, selected Tokens are no longer proposed in the drop-down menu. You can deactivate and activate this behavior with the setExcludeSelectedTokens(Boolean excludeSelectedTokens) method and check the current setting with the isExcludeSelectedTokens() method.

tokenFieldRendered.png

Example expression that returns a token field

def TokenField tf:= new TokenField("");
tf.setOptions([ "value1" -> "displayed option 1", "value2" -> "displayed option 2"]);
tf.setBinding(&selectedItems);
//tf.setOnChangeListener( { _-> select.refresh() });
tf;

Tree (forms::Tree)

Important: In the Vaadin 8 implementation, this component is not supported. For more information, refer to information on Vaadin 8 upgrade.

The Tree ( ) component serves as a picker of one item from an expandable tree hierarchy.

The tree hierarchy is defined by the data source and what is displayed as node labels for the tree objects is defined by the caption provider.

  • Data source can be of the following types:
    • ClosureTreeDataSource: the input object of the closure is the clicked node and it returns a list of objects that represent the data source;

      Example ClosureTreeDataSource:

      new ClosureTreeDataSource(
        { node:Object ->
             def List<Object> result;
             if node == null then
               result := getAllApplicants();
             else
               if (node.getType() == Applicant and (node as Applicant).address != null) then
                 result := [(node as Applicant).address];
               else
                 result := [];
               end;
             end;
           result;
        }
      )
    • SimpleTwoLevelTreeDS: two-level tree

      Example SimpleTwoLevelTreeDS data source:

          def SimpleTwoLevelTreeDS tree := new SimpleTwoLevelTreeDS(
             [ "eva" -> ["climbing", "painting"], "juraj" -> ["reposing", "windsurfing"] ]
          )
      

      The tree identifies the node based on designated IDs. Therefore an object can appear multiple times in a tree. The select(<VALUE>) call on the tree, selects the first occurrence of the object.

  • Caption provider can be of the following types:
    • IdentityValueProvider: the current row
    • ConstantValueProvider: node labels are constant values
      new ConstantValueProvider("Constant node label")
    • ClosureValueProvider: closure that returns the labels for every node type including null value
      new ClosureValueProvider(
        { x:Object ->
          if typeOf(x) == type(Applicant) then
             (x as Applicant).name + (x as Applicant).surname;
          else
            if x != null then
             (x as Address).country;
            else
              null
            end
          end
        }
      )

Where the selected value is stored is defined by the Binding property. To set and get the selected value programatically, use the setValue() and getValue() methods.

Setting a selected node in a Tree component

//Data source:
//def SimpleTwoLevelTreeDS tree := new SimpleTwoLevelTreeDS(
// [ "eva" -> [climbVar, "painting"], "juraj" -> [ "windsurfing"] ]
// )
//setting climbVar as the selected value in the tree:
c.setValue(climbVar);

Upload (forms::Upload)

The Upload component allows the user to upload a file to the server. Depending on its field style setting, it renders either as an upload button or as an input field for a file, a Browse and an upload button; Note that a file selected for download is not saved when calling Forms.save().

You can define the action performed when the file has been uploaded with the setUploadResultListener() method.

Example expression that returns an Upload component

def Upload up := new Upload();
//only presets the file type in the Browse popup:
up.setAcceptedMimeTypes("text/plain");
//render the upload button AND a "Choose File" button:
up.setFieldStyle(UploadFieldStyle.FileFieldAndButton);
//perform this action when the file is uploaded:
up.setUploadResultListener(
   { f:File, m:String ->
      if f==null then
      uploadOutcomeMessage.setValue("upload failed")
      else
        uploadedFile := f;
        uploadOutcomeMessage.setValue("upload success");
      end
   }
);
up
UploadRendered.png

Multi-File Upload (forms::MultiFileUpload)

The Multi-File Upload component allows the user to upload multiple files at once.

You can define the action performed when the file has been uploaded with the setAllFilesUploadedListener() method.

Example expression that returns an Upload component

def MultiFileUpload mfu := new MultiFileUpload();
mfu.setAllFilesUploadedListener(
   { e:AllFileUploadsDone ->
      if e.files==null then
          uploadOutcomeMessage.setValue("upload failed")
      else
          uploadOutcomeMessage.setValue("upload success");
      end
   }
);
mfu

Decision Table Editor

The Decision Table Editor component allows the user to view and modify a decision table on runtime from the Process Application.

You can save the underlying decision table object with the save() method call and load it with the load() call, possibly called from a listener. Like this, your users can promptly adapt the rules used by already running model instances and adjust the execution in steps when the decision table is used to evaluate a rule.

Important: The Decision Table Editor component is part of the dmn module of the Standard Library unlike the other components, which are provided by the forms module. Make sure to import the dmn module into your module before you use the component.

To add a decision table editor to a form, do the following:

  1. Insert the Decision Table Editor component into the form.
  2. Set the component Properties:
    • Decision Table: the instance of the decision table it will use
    • Rights: the rights of the Process Application user over the decision table

      By default, decision tables are read-only. To allow the user to work with the component freely, set Rights to [DecisionTableRights.CAN_EVERYTHING]. If the table is not read-only, make sure to save the changes to the table object with the <DecisionTableObject>.save(<StringIDOfTheTableObject>) method. Consider to attempt to load the decision table object, in case it already exists, as part of the form initialization, for example, in its constructor:

      
          public TrainingDaysForm() {
              //the form has the atd local variable of the type of the TrainingDays decision table:
               atd := new TrainingDays(false);
               //try to load it; if it is not loaded, create it and save it:
               if (atd.load("TrainingDaysDecisionTable") == false) then
                 atd := new TrainingDays(true);
                 atd.save("TrainingDaysDecisionTable");
               end;
          }
      

When rendered in the Process Application, an editable Decision Table Editor is edited similarly to its definition. Note that if you want to edit the rule description, single-click the description cell and the double-click the area displayed below.

editingDecisionTable.png
On information on how to design decision tables and use the Decision Table Editor, refer to the Decision Table chapter in the Modeling documentation or the tutorial on decision tables.

Slider (forms::Slider)

The Slider component serves to take a single input value of type Decimal from a value range. It is rendered as a bar with movable handle, with the bar representing the range and the handle the input value.

The bar range is set with the setMin() and setMax() methods. If unset, minimum is set to 0 and maximum to 100. Use getMin() and getMax() to get the set values.

The number of decimal places that the value is set to is set with the setDecimalPlaces() method.

The slider can be rendered horizontally or vertically: set the orientation with the setOrientation() method; for example, c.setOrientation(Orientation.Vertical)

Example expression that returns a Slider component

def Slider sl := new Slider("Value Select");
sl.setBinding(&decVar);
sl.setMin(0);
sl.setMax(10);
sl.setDecimalPlaces(2);
sl.setOrientation(Orientation.Vertical);
sl.setOnChangeListener( { _->select.refresh()});
sl