Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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. This way it is easy to separate you pricing calculations from input generations, and to reuse inputs across multiple logics.

Additionally, forms also allow for a larger degree of freedom than inputs generated in the input generation mode. For example, you can have input fields appear, disappear, or change according to what other input the end user provides.

embedded formImage Removed embedded formImage Added

To create a form, create a logic with default logic nature and return instances of ConfiguratorEntry and/or ConfiguratorEntryArray from its elements.

...

Form Field Sets (ConfiguratorEntry)

A form field set (ConfiguratorEntry) is a container for inputs that share the same purpose. A field set can be accompanied by a legend that describes the purpose of the field set.

single field setImage Removed single field setImage Added
Info
The configurator logic is executed each time the end user provides an input. This means that the input fields will be recreated on each execution. Therefore, to persist the value that the user just provided, you must explicitly set the value of the newly generated input field.
Code Block
languagegroovy
themeMidnight
linenumbersfalse
@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).

Code Block
languagegroovy
themeMidnight
titleAn element of a form logic (Configurator) that returns a form field set (ConfiguratorEntry).
linenumbersfalse
return getNameFieldSet()

Form Field Set Arrays (ConfiguratorEntryArray)

A field set array is a container for multiple form field sets.

multiple field setImage Removed multiple field setImage Added

Create a form field set array by providing the form field sets to api.createConfiguratorEntryArray():

Code Block
languagegroovy
themeMidnight
linenumbersfalse
return api.createConfiguratorEntryArray(timeFieldSet, countryFieldSet)

Where timeFieldSet and countryFieldSet are instances of ConfiguratorEntry:

Code Block
languagegroovy
themeMidnight
linenumbersfalse
@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, meaning they can change appearance according to the input provided by the end user.

In the example below, the country input is not made visible until the end user chooses a region first. If the user changes the region, the country input is cleared.

interactive step 1Image Removed interactive step 2Image Removed interactive step 1Image Added interactive step 2Image Added
Code Block
languagegroovy
themeMidnight
titlehttps://github.com/pricefx/example-configuration/tree/main/pricefxSrc/CalculationLogic/Dashboard_SalesManager_Configurator/elements/Inputs.groovy
linenumbersfalse
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 a button.

open dialog buttonImage Removed form dialogImage Removed open dialog buttonImage Added form dialogImage Added
Code Block
languagegroovy
themeMidnight
linenumbersfalse
api.inputBuilderFactory()
            .createConfiguratorInputBuilder(
                    'Filters',
                    configuratorLogicName,
                    false   // ❶
            )
            .getInput()

❶ Open the form as a dialog, rather than embedding it.

...

Images

By setting the legend to an HTML img element, you can display an image inside a form:

image in configuratorImage Removed image in configuratorImage Added
Code Block
languagegroovy
themeMidnight
titlehttps://github.com/pricefx/example-configuration/tree/main/pricefxSrc/CalculationLogic/Library_Input/elements/Image.groovy
linenumbersfalse
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
}