Interactive Forms - Configurators

Configurator is a user-driven wizard-like input for fine-tuning product details. It can be handy in cases when the product is defined by multiple parameters. The main advantage of the Configurator is that it allows users to directly change parameters and based on this input they see additional data about the product. This data may also be reflected in the quoting process.

A configurator can be displayed either as a popup window or as in-line dynamic fields in the Input Parameters panel.

 Note the difference between the Clear and Undo buttons. While Clear sets all inputs to null, Undo restores all the inputs to its default value if there is such defined by the calculation logic.

See also a separate page about Input Builders.


In this section:

Defining Configurator

The Configurator form is defined by a dedicated generic calculation logic. The Configurator form consists of several "sections", and every "section" can contain several "inputs". These sections and inputs must be created in the logic. Usually, every element of the logic creates one "section" of the configurator form, typically with one input box.

 Keep in mind that the configurator initialization takes place in the SyntaxCheck mode. So if you have in your logic api.IsSyntaxCheck() set to “escape”, then your configurator will not be created.

Creating User Input Elements

The user input elements in the Configurator can be created in Groovy as follows:

def ce = api.createConfiguratorEntry() def meatParameter = api.inputBuilderFactory() .createOptionEntry("Meat") .setOptions(["Beef", "Lamb", "Pork"]) .buildContextParameter() return ce.createParameter(meatParameter,{"Beef"})

The function api.createConfiguratorEntry() creates two things at once – a new "section" and its "input".

 If a pop-up Configurator includes a required input and the user does not open it, the user will be able to save the document even though the input is not filled in. The reason is that the application is not able to check if there is a required input until the user opens the Configurator.

 See also the list of available input types.

Comparison of ConfiguratorEntry and ConfiguratorEntryArray

There are two ways to create a configurator:

  • You create one ConfiguratorEntry and add parameters to it and return that as result of an element.

  • You create multiple ConfiguratorEntry with parameters and wrap them in ConfiguratorEntryArray and return that instead. 

These two approaches are equivalent, but they are useful in different scenarios:

  • Array:

    • If you want to return multiple independent configurator entries from one element.

    • If you intend to create a kind of library logic with a possibility to reuse the same configurator code (fragment) at multiple places (e.g., several Quote Types, Dashboard filters, config wizard). An array is handy here because it can consist of multiple parts.

    • The array allows returning multiple entries from one logic element and it can be required, e.g., if you do cascading of inputs based on previous inputs values.

  • Multiple configurator entries with more than one parameter:

    • The main benefit is that they can share some configuration (e.g., a warning message).

You can use whatever combination you want, but in the end, from the user's perspective, only the entries matter, the array is just a way to return multiple entries from one element. There is no major difference in performance (if you create 3 configurator entries with 1 parameter each and put that into an array or create 1 configurator entry with 3 parameters). 

Setting/Resetting the Value of User Input

Every time the user changes the input, all elements are recalculated. This fact can be used to dynamically change the user input options and create a "wizard-like" walk-through.

If you need to hide some inputs completely (if prerequisite elements are not set by the user), use the following:

def req = input.Family // previous element required by this input if (req == null) { return null // user input is not even shown until "Family" is set by user }

Also, you may want to override the user selection if it is no longer valid:

if (input.Family == "invalid option") { ce.getFirstInput().value = "" }

The call ce.getFirstInput() gets the first input box in the Configurator Entry.

Disabling Refresh on Change

When an input is updated in the Configurator, the whole dialog is refreshed. If this is an issue for you (e.g., slowing down your work), you can disable the auto-refresh.

This option is supported by all input types.

Recalculating the Whole Document

You can trigger recalculation of the document (Quote, Agreement/Promotion, Rebate Agreement) from a configurator in the document's header or line items. Click the 'Confirm Changes' button to start the recalculation.

Switching to Vertical Layout

You can change the configurator's layout to vertical. The user input labels will be displayed above the input fields to make more horizontal space for the inputs.

To change the layout, use the method addAdditionalConfigValue("layout", "vertical"). 

 For in-line configurators, this functionality is supported only in Quotes, Agreements/Promotions and Rebate Agreements.

Decorating Configurator Using HTML and CSS

You can use the .message element, which is outputted to the user as HTML. This fact can be used to make the Configurator more user friendly and beautiful:

To display an error message in red is particularly handy:

You can even show an image inside the Configurator:

Note that this image has to be uploaded to some server first. Be also careful about the image dimensions which can disrupt the visual style of the Configurator.

Using/Calling Configurator from Quote

The Configurator form is defined by a separate calculation logic (defined in Price Setting) which is then called from the Quote pricing logic using this command:

Calling the configurator from logic
Calling the configurator from Groovy API

Retrieving User Input in the Quote Logic

The result value of a call Configurator() is a map of values.

The Quote pricing logic can retrieve the user input from the form using the MapValue function:

Using Hidden Input to Pass Data from Configurator to Pricing Logic

If you need to pass additional data from the Configurator to the main logic, you can create a new logic element and use the hidden input to do that:

Make sure these elements are set as visible, otherwise they won't show in the main logic. 

And again, retrieve data as usually in the main logic:

This is particularly handy for intermediate results calculated in the Configurator because it saves code and loading time. 

Passing Parameters to Configurator

The two involved logics ("main logic" and "configurator logic") do not share anything. As mentioned above, the only thing that is passed is the value of the Configurator, which is by definition a map with arbitrary key/value pairs. This however can also be used to pre-seed a Configurator or pass values.

In the main logic, you usually initialize the Configurator like this:

This results in a so-called context parameter with the name "Configurator A" with an empty value when the logic is run in the parameter determination mode.
However, you can fill the value also initially by some Groovy magic in the calling logic:

In your Configurator logic, you can then access this value like any other:

Option A:

Option B (without creating a Configurator input):

Using api.local to Pass Data between Elements in the Logic

Additional data between elements inside a configuration logic (not between logics) can be passed using the api.local storage:

... and in a later element:

This is useful if you use some data twice in Configurator logic, for example, if the part cost is retrieved in one element then there is another element to calculate the total product cost.

Learn more about Caching Strategies.

Found an issue in documentation? Write to us.