Rich UI validation and formatting
This topic briefly describes the Model, View, and Controller (MVC) way of organizing logic and then explores how Rich UI uses the idea of MVC to support validation and formatting.
MVC
- The view is the user interface, or the logic that supports the user interface, or the business data in the user interface
- The model is a database (or other data storage), or the logic that accesses a database, or the data that is sent to or retrieved from a database
The controller is the logic that oversees the transfer of data between the user interface and the database-access logic.
In many cases, the acronym MVC refers to processing across multiple platforms. For example, a Rich UI application on a Windows™ platform might be considered to be the view (and to include the controller), while a service that accesses a database might be considered to be the model.
- The view is a widget in the user interface. Data that is placed into that widget must be validated before it can be used in other processing. Application data that is intended for display by the widget must be formatted before display.
- The model is a data field that is internal to the application.
An EGL definition, the controller, lets you tie a specific view (a specific widget) to a specific model. The controller also oversees validations and format rules, as described later.
You can also define a form that identifies a set of display fields and the related controllers. In such a form, you can display the error messages that result from validations and formatting.
The next sections describe the Controller and how to work with it. For details on creating forms, see Form processing with Rich UI, which uses the mechanisms described here.
The Controller in Rich UI
nameField TextField;
name String {inputRequired=yes,
validationPropertiesLibrary=myLibrary,
inputRequiredMsgKey="requiredMessage"};name has the following properties:- inputRequired ensures the user will provide input to any widget (a view) that is associated with the data field (a model)
- validationPropertiesLibrary identifies
the library (stereotype
RUIPropertiesLibrary) that includes declarations for use in messages and other text. If you do not include this property, the EGL Runtime accesses default messages. For details on customizing validation messages in Rich UI, see Use of properties files for displayable text. - inputRequiredMsgKey identifies a customized validation message
nameController Controller
{ @MVC
{ model=name, view=nameField },
validators = [myValidationFunction01, myValidationFunction02]
};The declaration ties a specific model (the name field) to
a specific view (the nameField widget). In general,
only a widget of a special type can be a controller view, as noted
in Widgets that can be used as controller views.
- To transfer data from the view to the model, you validate the data and then commit the validated data. In most cases, the commit step removes formatting characters such as currency symbols.
- To transfer data from the model to the view, you publish the data. In most cases, the publish step formats the data for display.
Delegate
MVCValidatorFunction(input String in) returns(String?)
endInput to a validator is considered to be valid if the function returns an empty string or null, but not if the validator returns a string with content. Such a string is considered an error message. If a function returns an error message, the subsequent functions do not run.
nameField widget into the name field:if (nameController.isValid())
nameController.commit();
end
Validating the user input
- The isValid function is invoked whenever
the user moves the focus away from the widget. Also, your code can
invoke the function, which displays error messages that result from
a failed validation.
An error message is removed only when a successful validation occurs, not when the user moves the focus back to the widget.
- The validate function is invoked by
the isValid function and stores a message
for the first-found error, but does not display the message. You can
access the stored error message by invoking the controller-specific getErrorMessage function,
which has no parameters and returns a value of type STRING?.
Your code can invoke the validate function instead of the isValid function, for greater control. For example, your code might invoke the validate function to test whether to display a help page or to take some other action if an error is found, and you can avoid displaying an error message returned from the function.
- You can call the isControllerValid function to inspect the valid state of the controller without notifying the valid state change listener.
A related controller-specific function is isValidStateInitialized, which specifies if a controller-specific validation function (whether isValid or validate) ran at least once in the current execution of the Rich UI application. The function isValidStateInitialized has no parameters and returns a Boolean.
- DojoCurrencyTextBox
- DojoDateTextBox
- DojoTextField
- DojoTimeTextBox
- The error message that results from a failed view-level validation
is always displayed in a tooltip near the widget. When the widget
loses focus, the tooltip is hidden, and when the widget regains focus,
the tooltip is shown.
The behavior just described is a characteristic of Dojo.
- When the user moves the focus away from the widget, controller-level validation occurs; but only if the view-specific validation was successful.
- Runs the function referenced by the retrieveViewHelper property (not shown in our example), which identifies the function that retrieves the widget content. The function has no parameters and returns a string. You might use this function to convert the input in some way. However, you do not need to set the retrieveViewHelper property in most cases. In the absence of that property, the widget content is available as a string, for subsequent processing.
- Runs the functions referenced by the unformatters property (not shown in our example), which identifies an array of functions. Each has a string parameter (STRING in) and returns a string. You might use these functions to remove formatting characters from the input. The first-listed function accepts the string returned from the retrieveViewHelper function, and each of the later-listed functions accepts the string returned from the previous function. You might not need to set the unformatters property.
- Removes the formatting characters from the user input in accordance with that formatting properties, if any, that you specified in the source code. An example of a formatting character is the currency symbol, which is associated with the currency property. A second example are the separators specified by the dateFormat property.
- Returns control to the user if a validation error occurs related to data type; for example, the user may have typed a character when the model is a numeric field.
- Runs the elementary validations, as specified by EGL properties
that are set on the model, not on the view.
A later section lists the available properties, which include inputRequired, as shown in our example. (That property ensures the user will provide input to any widget that is associated with that the data field.)
Here are the possible outcomes of the elementary validations:- If any of the elementary validations fail, control returns to
the user. If the controller is in a form, a message associated with
the first failed validation is stored.
You can accept the default EGL message for a given validation; but if you want to specify your own message, review the description in Use of properties files for displayable text.
- If all the elementary validations are fulfilled, the validators run, as described next.
- If any of the elementary validations fail, control returns to
the user. If the controller is in a form, a message associated with
the first failed validation is stored.
- Runs the validators in the order specified in the controller validators array.
Each validator accepts the input string (STRING in) without formatting
characters such as the currency symbol; and each validator returns
a string or a null. (The return value is of type STRING?.) If the validator returns a null or blank, the EGL Runtime considers the validation to have succeeded. However, the following statements apply if the validator returns a different value, for example, a value retrieved from a properties file, as described in Use of properties files for displayable text:
- The EGL Runtime considers the validation to have failed.
- Control immediately returns to the user; in that case, the subsequent validators do not run.
- The returned string is stored as an error message. For details that are specific to the EGL Dojo widgets that support view-level validation, see Displaying a controller-level error message in an EGL Dojo widget.
You can write a validator that is accessed by multiple controllers. The reuse is possible because you can now identify the controller, as shown here:function commonValidator(input string in) returns(string?) currController Controller = MVCLib.getCurrentContext(); viewId string = currController.view.id; end
Last, the publishMessageHelper property takes a function that has a single parameter, which is modified by IN, and no return value. This function is invoked when the widget gains focus, and the input to that function is the last message that was stored when the widget lost focus.
Changing the display of invalid input and handling error messages
By default, a widget with invalid content is displayed with a style specified in a Cascading Stylesheet (CSS) class; specifically, the initial class such as EglRuiTextField, along with the following, secondary class: FormErrorEditor. A web designer in your organization is likely to set up the style sheet for best effect.
You can assign a different set of CSS classes (or a different CSS ID) in response to validation failure; or you can change another aspect of the displayed output. For example, you can assign CSS classes to a label, as occurs (by default) if you use a validating form. (For details, see Form processing with Rich UI.)
- Set the controller property validStateSetter, which identifies a function for the EGL runtime to invoke at the end of validation.
- Create the function, which has two parameters and no return value.
The first parameter receives the widget that holds the data being
validated. The second parameter indicates whether the validation succeeded.
Here is the Delegate part to which each function must conform:
Delegate MVCValidStateSetter(widget Widget in, valid boolean in) end - In that function, assign a different or additional class (or a different CSS ID) to the widget that has invalid content or, more likely, to the label of that widget.
In the same function, you can access controller-level error messages by invoking the controller-specific getErrorMessage function. As noted earlier, that function has no parameters and returns a value of type STRING?.
Displaying a controller-level error message in an EGL Dojo widget
- In relation to the EGL Dojo widgets that support view-level validation,
you can place the message in the tooltip where any message from a
view-level validation is displayed. In this case, the widget immediately
displays an error indicator in response to the error, but the controller-level
message is displayed only after the widget gains focus. (For the earlier
description of view-level validation, see Validating the user input.)
If the widget is in a form, you can prevent the controller-level error message from being displayed in an error label by removing the error label.
- In relation to any EGL or EGL Dojo widget, you can place the message
in an error label, as described in Form processing with Rich
UI. In this case, the widget immediately displays an error
indicator in response to the error, and the message is displayed as
soon as the error occurs.
If you decide to place the message in an error label and are using an EGL Dojo widget that supports view-level validation, you can prevent the message from being displayed in the tooltip. To prevent the duplicate display, set the controller-specific publishMessageHelper property to null or assign your own function to that property. If you do not set the property or assign your own function, an internal EGL function is invoked to direct the error message to the tooltip.
As noted in the documentation for the EGL Dojo widgets that support view-level validation, you can set an error indicator by invoking the widget-specific showErrorIndicator function and can display an error message by invoking the widget-specific showErrorMessage function.
Committing the validated input
- The retrieveViewHelper property identifies the function that retrieves the widget content. The function has no parameters and returns a string. You might use this function to convert the input in some way. However, you do not need to set the retrieveViewHelper property in most cases. In the absence of that property, the widget content is available as a string, for subsequent processing.
- The unformatters property identifies an array of functions. Each has a string parameter (STRING in) and returns a string. You might use these functions to remove formatting characters from the input. The first-listed function accepts the string returned from the retrieveViewHelper function, and each of the later-listed functions accepts the string returned from the previous function. You might not need to set the unformatters property.
- Formatting characters are removed from the user input in accordance with the formatting properties, if any, that you specified in the source code. An example of a formatting character is the currency symbol, which is associated with the currency property. A second example are the separators specified by the dateFormat property.
- The commitHelper property identifies the function that assigns a value to the model. The function takes a string parameter and no return value. You might not need to set this property. In its absence, the model receives the string that was provided by an earlier function, if any, and that no longer includes formatting characters.
Publishing the model data
publish function, data is transferred
from the model to the view. During that process, several functions
are invoked, as determined by a set of controller properties that
give you many options. Here are the properties:- The retrieveModelHelper property identifies the function that retrieves the data content. The function has no parameters and returns a string. You might use this function to convert the output in some way. However, you do not need to set the retrieveModelHelper property in most cases. In the absence of that property, the model content is made available as a string, for subsequent processing.
- Formatting characters are added to the data content in accordance with the formatting properties, if any, that you specified in the source code. An example of a formatting character is the currency symbol, which is associated with the currency property. A second example are the separators specified by the dateFormat property.
- The formatters property identifies an array of functions. Each has a string parameter (STRING in) and returns a string. You might use these functions to format the output. The first-listed function accepts the string returned from the retrieveModelHelper function, with any formatting characters added in step 2. Each of the later-listed functions accepts the string returned from the previous function. You might not need to set the formatters property.
- The publishHelper property identifies the function that assigns a value to the view. The function has a string parameter (STRING in) and no return value. You might not need to set this property. In its absence, the view receives the string that was provided by an earlier function, if any, and that includes formatting characters.
Validation and formatting properties
- F is for formatting. A property in this category removes formatting characters during commit and adds formatting characters during publish. Any of these properties can result in the display of an error message; for example, if an input date is significantly different from the required date format, or if an integer value is a number other than 0 or 1 but is associated with isBoolean.
- V is for input validation.
- currency (F)
- currencySymbol (F)
- dateFormat (F)
- fillCharacter (F)
- inputRequired (V)
- inputRequiredMsgKey (V)
- isBoolean (F)
- isDecimalDigit (V)
- isHexDigit (V)
- lowercase (F)
- minimumInput (V)
- minimumInputMsgKey (V)
- numericSeparator (F)
- sign (F)
- timeFormat (F)
- timestampFormat (F)
- typeChkMsgKey (V)
- uppercase (F)
- validValues (V)
- validValuesMsgKey (V)
- zeroFormat (F)
- inputRequiredMsgKey (V)
- minimumInputMsgKey (V)
- typeChkMsgKey (V)
- validValuesMsgKey (V)
You can specify the validation and formatting properties on DataItem definitions, on variables, and on Record fields; but they are in effect for a given Rich UI controller only if you specify the @MVC property when declaring the controller.