Forms — also referred to as Configurators — is a structure that contains a set of input fields. You can create your own forms and include these in your logics. In this, way it is easy to separate you pricing calculations from input generations, and to reuse input across multiple logics.
Additionally, forms also allows for a larger degree of freedom than inputs that are generated in syntax check mode. For example, you can have input fields appear, disappear, or change according to what other input the end-user provides.
To create a form, create a logic with default logic nature and return instances of ConfiguratorEntry
and/or ConfiguratorEntryArray
from its elements.
Including Forms in Other Logics
To include a form in your logic, build an input that references the form by its name:
api.inputBuilderFactory() .createConfiguratorInputBuilder('form', configuratorLogicName, true) .getInput()
processor.addOrUpdateInput( 'ROOT', api.inputBuilderFactory() .createConfiguratorInputBuilder('form') .buildMap() )
def formSection = api.createConfiguratorEntry() formSection.setInputs([ api.inputBuilderFactory() .createConfiguratorInputBuilder('form') .buildContextParameter() ]) return formSection
Any inputs that are part of the form can be read normally:
input.nameOfInput as ValueType
Form Field Sets (ConfiguratorEntry
)
A form field set (ConfiguratorEntry
) is a container for inputs that shares the same purpose. A field set can be accompanied by a legend that describes the purpose of the field set.
@Field String INPUT_FIRST_NAME = 'firstName' @Field String INPUT_LAST_NAME = 'lastName' ConfiguratorEntry getNameFieldSet(){ def firstNameInput = api.inputBuilderFactory() // ❶ .createStringUserEntry(INPUT_FIRST_NAME) .setValue(input[INPUT_FIRST_NAME) // ❷ .setLabel('First Name') .buildContextParameter() def lastNameInput = api.inputBuilderFactory() // ❶ .createStringUserEntry(INPUT_LAST_NAME) .seValue(input[INPUT_LAST_NAME]) // ❷ .setLabel('Last Name') .buildContextParameter() def nameFieldSet = api.createConfiguratorEntry() nameFieldSet.inputs = [firstNameInput, lastNameInput] nameFieldSet.message = 'Your Name' return nameFieldSet }
❶ Create the two inputs that the form field set will contain.
❷ Set the value of the input field to the value that the user had already provided (if any).
Use as such
return getNameFieldSet()
Form Field Set Arrays (ConfiguratorEntryArray
)
A field set array is a container for multiple form field sets.
Create a form field set array by providing the form field sets to api.createConfiguratorEntryArray()
:
return api.createConfiguratorEntryArray(timeFieldSet, countryFieldSet)
Where timeFieldSet
and countryFieldSet
are instances of ConfiguratorEntry
:
@Field String INPUT_YEAR = 'year' @Field String INPUT_COUNTRY = 'country' ConfiguratorEntry getTimeFieldSet(){ def fieldSet = api.createConfiguratorEntry() fieldSet.message = 'Filter by Year' fieldSet.inputs = [yearInput] return fieldSet } ConfiguratorEntry getCountryFieldSet(){ def fieldSet = api.createConfiguratorEntry() fieldSet.message = 'Filter by Country' fieldSet.inputs = [countryInput] return fieldSet } ContextParameter getYearInput(){ return api.inputBuilderFactory() .createIntegerUserEntry(INPUT_YEAR) .setLabel('Year') .setValue(input[INPUT_YEAR]) .buildContextParameter() } ContextParameter getCountryInput(){ return api.inputBuilderFactory() .createStringUserEntry(INPUT_COUNTRY) .setLabel('Country Code') .setValue(input[INPUT_COUNTRY]) .buildContextParameter() }
Interactive Forms
Forms can be made interactive, that is to change appearance according to what input the end-user provides.
In the example below, the country input is not made visible until the end-user has chosen a region first. If the changes the region, the country input is cleared.
return getCountryFieldSet() @Field String INPUT_REGION = 'region' @Field String INPUT_COUNTRY = 'country' ConfiguratorEntry getCountryFieldSet(){ def fieldSet = api.createConfiguratorEntry() fieldSet.message = 'Filter by Country' fieldSet.inputs = regionValue ? [regionInput, countryInput] : [regionInput] return fieldSet } // Methods for creating inputs ContextParameter getRegionInput() { // Lib def regionLib = libs.Library_Geography.Region def allRegions = regionLib.findAllRegions() return api.inputBuilderFactory().createOptionEntry(INPUT_REGION) .setOptions(allRegions) .setValue(regionValue) .buildContextParameter() } ContextParameter getCountryInput() { // Lib def countryLib = libs.Library_Geography.Country def countryInfo = countryLib.findCountriesByRegion(regionValue) Map<String, String> countryCode2CountryName = countryInfo.collectEntries { row -> [(row[countryLib.FIELD_COUNTRY_CODE]): row[countryLib.FIELD_COUNTRY_NAME]] } def values = countryCode2CountryName.keySet().toList() def value2Label = countryCode2CountryName // If the user changed the region, reset the value def isCountryInRegion = countryLib.isCountryInRegion(countryValue, regionValue) def newCountry = isCountryInRegion ? countryValue : null return api.inputBuilderFactory().createOptionEntry(INPUT_COUNTRY) .setOptions(values) .setLabels(value2Label) .setValue(newCountry) .buildContextParameter() } // Methods for reading user input values String getRegionValue() { return input[INPUT_REGION] as String } String getCountryValue() { return input[INPUT_COUNTRY] as String }
Form Dialogs
A form can either be embedded, or it can be made to appear in a dialog. To open the dialog, the user will have to click on a button.
api.inputBuilderFactory() .createConfiguratorInputBuilder( 'Filters', configuratorLogicName, false // ❶ ) .getInput()
❶ Open the form as a dialog, rather than embedding it.
Styles Legends
Legends can be styled, by providing the message
as an HTML string with inline styling:
def nameFieldSet = api.createConfiguratorEntry() nameFieldSet.inputs = [myInput] nameFieldSet.message = '<code style="font-weight: bold;">Your Name</code>' // ❶
❶ The legend is wrapped within a code
element and styled with bold
.
Images
By setting the legend to a HTML img
element, you can display an image inside a form:
ConfiguratorEntry imageFieldSet(String sku, String alt){ def imageFieldSet = api.createConfiguratorEntry() // Add a dummy input, or the backend will throw an Exception def dummyInput = api.inputBuilderFactory().createHiddenEntry(sku).buildContextParameter() imageFieldSet.inputs = [dummyInput] String partition = api.currentPartitionName() def productImageUrl = "/pricefx/${partition}/productimages.get/${sku}?predefinedSize=enlarged_thumbnail" imageFieldSet.message = """<img src="$productImageUrl" alt="$alt"/>""" return imageFieldSet }