...
When a form step is submitted, the posthandling process is followed. In this case, the routing result is handled and the user is redirected accordingly. Form logic can be extended by installing a form logicProvider
formlogicProvider
plugin. Such form logicComponents
can be written in either Java, JavaScript or a combination of both. What actually happens when a form is rendered or submitted is much more complex (see The Form Engine for more details).
...
This package provides interfaces that enable plugin developers to create their own form fragments. A form fragment uses the FormFragmentComponent
to become a component, and is therefore able to be managed by the Component Manager. The FormFragmentComponent
interface ensures a unified way of creating form fragment instances through the createInstance()
method. The FormFragmentComponentType
interface introduces the component type that identifies the class of form fragment components. The FormFragmentComponentDefinition
defines the relationship between the component, component type, form fragment implementation class and more.
nl.gx.forms.wmpformapi.plugin.
...
formlogicProvidertype
This package provides interfaces that enable plugin developers to write their own form logic. The form logicProviderComponent
formlogicProviderComponent
is the XperienCentral component that provides form logic (routers, handlers and validators). Form logic typically implements this interface. The form logicProviderComponentType
formlogicProviderComponentType
interface introduces the component type that identifies the class of form logic components. The form logicProviderComponentDefinition
formlogicProviderComponentDefinition
defines the relation between the component, component type, form logic implementation class, and so forth. All form logic components typically implement the form logicProviderService
formlogicProviderService
, which allows them to be executed by the form engine.
...
The following table shows the Java interfaces used by the Interactive Forms form fragments.
Form Fragment Name | Java Interface |
---|---|
Text | nl.gx.forms.wmpformfragments.api.FormFragmentTextInput |
Number | nl.gx.forms.wmpformfragments.api.FormFragmentNumberInput |
Date | nl.gx.forms.wmpformfragments.api.FormFragmentDateInput |
Password | nl.gx.forms.wmpformfragments.api.FormFragmentPasswordInput |
Textarea | nl.gx.forms.wmpformfragments.api.FormFragmentTextArea |
Radio | nl.gx.forms.wmpformfragments.api.FormFragmentRadioList |
Checkbox | nl.gx.forms.wmpformfragments.api.FormFragmentCheckboxList |
Dropdown | nl.gx.forms.wmpformfragments.api.FormFragmentDropDownList |
Upload | nl.gx.forms.wmpformfragments.api.FormFragmentFileUpload |
nl.gx.forms.wmpformfragments.api.FormFragmentEmailInput | |
Columns | nl.gx.forms.wmpformfragments.api.FormFragmentColumns |
Section | nl.gx.forms.wmpformfragments.api.FormFragmentSection |
Form Section | nl.gx.forms.wmpformfragments.api.form.FormFragmentFormSection |
Repeat | nl.gx.forms.wmpformfragments.api.form.FormFragmentRepeat |
Next Button | nl.gx.forms.wmpformfragments.api.FormFragmentButton |
Back Button | nl.gx.forms.wmpformfragments.api.FormFragmentBackButton |
Paragraph | nl.gx.forms.wmpformfragments.api.FormFragmentParagraph |
Overview | nl.gx.forms.wmpformfragments.api.FormFragmentOverview |
...
Execute the following command to generate the
helloworldfragment
plugin:mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=nl.gx.forms.wmpformarchetypes -DarchetypeArtifactId=wmpformfragment-archetype -DarchetypeVersion=10.10.0 -DgroupId=com.gxwebmanager.helloworld -DartifactId=helloworld -Dclassprefix=HelloWorld -s <my_path_to_settings.xml>\settings.xml
Execute the following command to generate the
helloworldlogicprovider
plugin:mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=nl.gx.forms.wmpformarchetypes -DarchetypeArtifactId=wmpform logicproviderwmpformlogicprovider-archetype -DarchetypeVersion=10.10.0 -DgroupId=com.gx.webmanager.helloworld -DartifactId=helloworld -Dclassprefix=HelloWorld -s <my_path_to_settings.xml>\settings.xml
...
The implementation class (for example, CustomFragmentImpl
) must contain the method getDefaultValidators()
. This method returns the validator(s) that you want to use by default. If the fragment is added to the form step in the Interactive Forms interface, this set of validators will be assigned. The validators that are retrieved by this method have to be present in the framework. Create Your Own Form Logic Components explains how to create a fragment validator. Suppose a fragment validator is present in the bundle activator:
Code Block | ||
---|---|---|
| ||
form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl def = new form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl(false, form logicProviderComponentDefinitionformlogicProviderComponentDefinition.FORM_LOGIC_PROVIDER_TYPE_FRAGMENTVALIDATOR, pluginConstants.MY_VALIDATOR_IDENTIFIER); |
...
Form Logic is a generic term for handlers, routers, form validators and fragment validators. A form logic component implements both the form logicProvidercomponent
formlogicProvidercomponent
interface and the form logicProviderService
formlogicProviderService
interface. Usage of these interfaces requires the implementation of the run()
method.
...
Code Block | ||
---|---|---|
| ||
class implements form logicProvidercomponentformlogicProvidercomponent,formformlogicProviderService logicProviderService { public RoutingResult run(FormScope scope, Map<String, Object> parameters,Map<String, Object> languageLabels) {...} } |
...
If null
is returned, there is no routing result, therefore the next logic component in the queue will be handled. If a RoutingResult
is returned, execution within the handler queue is stopped and the routing result is handled. Because the form logicProvidercomponent
formlogicProvidercomponent
class is the action class of the logic component, the form logicProviderComponentDefinition
formlogicProviderComponentDefinition
object will register the form logic component. This definition is added to the bundle Activator of a plugin.
...
When a form logic (provider) component (definition) is added to the XperienCentral framework (by deploying a plugin), a form logicComponentDefinition
object will be registered. In other words, the form logicComponentDefinition
object is the entity reference of the form logic component. The method getform logicProviderComponentgetformlogicProviderComponent()
returns the form logic provider component of this entity.
...
The Interactive Forms component uses these subinterfaces according to the form logicProviderType
formlogicProviderType
that is assigned to the form logicProviderComponentDefinition
formlogicProviderComponentDefinition
in the activator class. Registering a logic component in the bundle Activator is similar for all form logic component types. The following code sample shows how to define a fragment validator:
...
Code Block | ||
---|---|---|
| ||
private form logicProviderComponentDefinitionformlogicProviderComponentDefinition getBankAccountValidatorDefinition() { form formlogicProviderComponentDefinitionImpl logicProviderComponentDefinitionImpl def = new form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl(false, form logicProviderComponentDefinitionformlogicProviderComponentDefinition. FORM_LOGIC_PROVIDER_TYPE_FRAGMENTVALIDAT OR, pluginConstants.BANKACCOUNT_VALIDATOR_IDENTIFIER); def.setId(pluginConstants.BANKACCOUNT_VALIDATOR_COMPONENT_ID); def.setName(pluginConstants.BANKACCOUNT_VALIDATOR_COMPONENT_NAME); def.setDescription(pluginConstants.BANKACCOUNT_VALIDATOR_COMPONENT_DESCR); def.setJsFilename("bankaccount_validator.js"); def.setTypeId(form logicProviderComponentTypeformlogicProviderComponentType.class.getName()); def.setImplementationClassName(Simpleform logicComponent.class.getName()); def.setProperties(new Hashtable<String, String>()); def.addRequiredParameter(ParameterDefinition.PARAMETER_TYPE_FORMFRAGMENT_IDENTIFIER, nl.gx.forms.wmpformapi.pluginConstants.VALIDATOR_FRAGMENT_PARAMETER, nl.gx.forms.wmpformapi.pluginConstants.VALIDATOR_FRAGMENT_PARAMETER); def.setAllowedToRunClientside(true); def.addLanguageLabelMapping("INVALID_BANKACCOUNT", "invalid_bankaccount"); def.setTitleLanguageLabel("wmpform logicprovidersnlwmpformlogicProvidersnl.validator.bankaccountvalidator.title"); return def; } |
...
The constructor of the component definition requires a form logicProviderComponentDefinition
formlogicProviderComponentDefinition
type as a (second) parameter. The form logicProviderComponentDefinition
formlogicProviderComponentDefinition
defines four types:
FORM_LOGIC_PROVIDER_TYPE_FRAGMENTVALIDATOR
FORM_LOGIC_PROVIDER_TYPE_FORMVALIDATOR
FORM_LOGIC_PROVIDER_TYPE_ROUTER
FORM_LOGIC_PROVIDER_TYPE_HANDLER
...
The implementation class of this component is the Simpleform logicComponent
class. This class implements the form logicProviderComponent
formlogicProviderComponent
class and has been used as a base or dummy form logic provider component. It is possible to use such a (empty) class in your plugin as the implementation class for a form logic provider that has only a JavaScript implementation. A dummy class should resemble the following:
...
Code Block | ||
---|---|---|
| ||
package nl.gx.forms.yourform logicprovidertypeyourformlogicProvidertype.impl; import nl.gx.forms.wmpformapi.plugin.form logicprovidertype.form logicProviderComponentformlogicProvidertype.formlogicProviderComponent; import nl.gx.XperienCentral.plugin.foundation.ComponentBase; public class Simpleform logicComponent extends ComponentBase implements form logicProviderComponentformlogicProviderComponent { } |
Note |
---|
This class doesn't implement the |
...
The second parameter refers to the name/identifier of this parameter. This identifier can be used as a reference in the run()
method of your form logicProviderComponent
formlogicProviderComponent
class. In Form Validator the retrieval parameters values are described. The third parameter refers to the language label that will be used in the user interface. (It should be present in the language_labels_xx
.properties file.) For a fragment validator, one specific parameter has to be defined. It should be a required parameter of the PARAMETER_TYPE_FORMFRAGMENT_IDENTIFIER
type. For example:
...
Creating a simple (that is, JavaScript only) fragment validator definition is fairly straightforward. First, add a componentDefinition
to your bundle Activator. Next, implement a JavaScript validator function. Finally, implement a dummy form logicProviderComponent
formlogicProviderComponent
class and, after deploying the plugin, the validator is ready to use.
...
In the code example above, the validateFormFragment()
method checks to see whether the precondition for the fragment is met. If so, it retrieves the validators that are assigned to the form fragment. The executeform logicComponent()
method that is called for a set of validators will retrieve and execute the validation action. This action could be either based on JavaScript or Java code. First, the JavaScript logic will be retrieved from the form logicComponentDefinition
. If no JavaScript is defined, the form logicProviderComponent
formlogicProviderComponent
object is retrieved and the run()
method will be called. However, this is only done when the form logicProviderComponent
formlogicProviderComponent
is an instance of the form logicProviderService
formlogicProviderService
, therefore be sure that custom-defined form logicProviderComponent
formlogicProviderComponent
implements the form logicProviderService
formlogicProviderService
interface.
If neither a JavaScript source nor a Java implementation is available, the FormengineService
will log the (severe) message: No implementation found for form logic component. Additionally, a (custom) FormFagment
class should (indirectly) implement the BasicFormInputFragment
interface if you want to perform server side validation. This interface requires the implementation of the method getDefaultValidators()
. This particular method (again) could bring up the question, how can default Fragment validators be assigned to fragments?
...
This identifier is already introduced in the component definition of the validator in the bundle Activator:
Code Block | ||
---|---|---|
| ||
form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl def =new form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl(false, form logicProviderComponentDefinitionformlogicProviderComponentDefinition.FORM_LOGIC_PROVIDER_TYPE_FRAGMENTVALIDATOR,pluginConstants.HELLOWORLD_VALIDATOR_IDENTIFIER); |
...
To include a Form Validator in your plugin start with adding the definition type FORM_LOGIC_PROVIDER_TYPE_FORMVALIDATOR
in your bundle Activator. For example:
Code Block | ||
---|---|---|
| ||
form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl def =new form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl(false, form logicProviderComponentDefinitionformlogicProviderComponentDefinition.FORM_LOGIC_PROVIDER_TYPE_FORMVALIDATOR,pluginConstants.HELLOWORLD_MYFORMVALIDATOR_IDENTIFIER); def.setId(pluginConstants.DATEDAYRANGE_VALIDATOR_COMPONENT_ID); def.setName(pluginConstants.DATEDAYRANGE_VALIDATOR_COMPONENT_ID); def.setDescription(pluginConstants.DATEDAYRANGE_VALIDATOR_COMPONENT_DESCRIPTION); def.setTypeId(form logicProviderComponentTypeformlogicProviderComponentType.class.getName()); def.setImplementationClassName(Simpleform logicComponent.class.getName()); def.setJsFilename("helloworld_formvalidator.js"); def.setProperties(new Hashtable<String,String>()); def.addRequiredParameter(ParameterDefinition.PARAMETER_TYPE_FORMFRAGMENT_IDENTIFIER "anyfragment","helloworldformvalidator.anyfragment"); def.addOptionalParameter(ParameterDefinition.PARAMETER_TYPE_STRING,"anyinteger","helloworldformvalidator.anyinteger"); def.setAllowedToRunClientside(false); def.addLanguageLabelMapping("ILLEGAL_VALUE","helloworldformvalidator.illegal_value"); def.addLanguageLabelMapping("VALUE_TO_BIG","helloworldformvalidator.fragment_value_max_exceeded"); def.setTitleLanguageLabel("helloworldformvalidator.title"); |
...
The Form Logic components discussed so far have been limited to JavaScript implementations of the action logic. In this part the focus is on a Java implementation, more specifically a Java implementation of a Form Handler. Defining the form handler starts with a registration via the Activator class of your plugin. This class should register a form logicProviderComponentDefinition
formlogicProviderComponentDefinition
object of the Handler Type (FORM_LOGIC_PROVIDER_TYPE_HANDLER
). For example:
Code Block | ||
---|---|---|
| ||
form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl def = new form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl(false,form logicProviderComponentDefinitionformlogicProviderComponentDefinition.FORM_LOGIC_PROVIDER_TYPE_HANDLER,"YOURIDENTIFIERHERE"); def.setTypeId(form logicProviderComponentTypeformlogicProviderComponentType.class.getName()); def.setImplementationClassName(YOURHANDLERCLASS.class.getName()); def.addLanguageLabelMapping(YOURHANDLERCLASS.ERROR_SENDEMAIL_FAILED,"error_sendemail_failed"); def.addLanguageLabelMapping(YOURHANDLERCLASS.MESSAGE_SENDEMAIL_OK,"message_sendemail_ok"); def.setTitleLanguageLabel("helloworld.handler.YOURHANDLERCLASS.title"); |
...
Code Block | ||
---|---|---|
| ||
def.addRequiredParameter( ParameterDefinition.PARAMETER_TYPE_STRING, //Type parameter YOURCONSTANTSCLASS.PARAM_URL, //Name "form logic.handler.addtosessionhandler.url"); // Titel of interface def.setTypeId(form logicProviderComponentTypeformlogicProviderComponentType.class.getName()); def.setImplementationClassName(YOURHANDLERCLASS.class.getName()); def.addLanguageLabelMapping(YOURHANDLERCLASS.ERROR_SENDEMAIL_FAILED,"error_sendemail_failed"); def.addLanguageLabelMapping(YOURHANDLERCLASS.MESSAGE_SENDEMAIL_OK,"message_sendemail_ok"); def.setTitleLanguageLabel("helloworld.handler.YOURHANDLERCLASS.title"); |
...
Code Block | ||
---|---|---|
| ||
private form logicProviderComponentDefinitionformlogicProviderComponentDefinition getGoToPageRouterDefinition() { Class myClass = GoToPageRouter.class; form logicProviderComponentDefinitionImpl formlogicProviderComponentDefinitionImpl def = new form logicProviderComponentDefinitionImplformlogicProviderComponentDefinitionImpl(false, form logicProviderComponentDefinitionformlogicProviderComponentDefinition.FORM_LOGIC_PROVIDER_TYPE_ROUTER, "GoToPage"); def.setId(myClass.getName()); def.setName(myClass.getName()); def.setDescription(myClass.getName()); def.setTypeId(form logicProviderComponentTypeformlogicProviderComponentType.class.getName()); def.setImplementationClassName(myClass.getName()); def.setProperties(new Hashtable<String, String>()); def.addRequiredParameter(ParameterDefinition.PARAMETER_TYPE_PAGE, GoToPageRouter.PARAM_PAGE, "page"); def.setTitleLanguageLabel("wmpform logic.router.goto_page_router.title"); return def; } |
...