Configurator Forms (Conceptual Guide)
You’re negotiating a Quote for a product, which requires the Sales Person to “configure” the product - that is to enter several parameters about the product, which influence the final Price. But the selection of the parameters depends on the previous choices, so it’s never the same.
What Is a Configurator
Configurator is an interactive form with multiple inputs, where values selected in one input field can influence visibility of other input fields or values available in those input fields.
The form can dynamically change after each change done by user. Anytime the user enters a value or selects a value, the Configurator logic is executed and can modify the list of input fields and their values.
The form content and dynamic behavior is defined in a separate Configurator logic. It is of Generic/Default logic type.
Buttons Behavior
OK – Closes the form and remembers the values of the input fields.The values entered by the user will be used once the user Recalculates the Quote (or refreshes the Dashboard).
Cancel – Closes the form and forgets all the values modified by the user.
Clean – Sets all inputs to empty value.
Reset – Restores all the inputs to its default value (if defined in the form).
Schema
Form – Interactive form, called Configurator.Each form is defined in its own logic.
Section – Each form can have more Sections. Each section groups together more Input fields, usually somehow related.
Input field – Any kind of input field available in Pricefx - number, dropdown, hidden, etc.Note: "Hidden" input can be useful for passing additional information calculated by the Configurator logic back to the Main logic.
Flow of Usage
User adds a new product/line to a quote.
The quote line logic is executed in Input Generation mode.
It inserts a reference to the Configurator i.e., a placeholder saying: here I want to show the Configurator.
The system collects the definition of the input fields, including the Configurator reference.
The UI renders the line item input fields.
The reference to Configurator is rendered as a Button. (It’s also possible to use "Inline" configurator, which renders in another way.)
The user clicks the button (which should open the Configurator).
The system runs the Configurator logic to create all the form’s sections and input fields.
The UI renders the Form on the screen.
The user selects a value in the form’s input field. This triggers a refresh of the whole Configurator form, i.e.:
The system will execute the Configurator logic.
It can read the values selected by the user.
It (again) creates all the form’s sections and input fields.
The UI refreshes the form’s inputs on the screen.
By default, the Configurator form will refresh every time when some input value is changed by the user, i.e., the Configurator logic will be executed again and the content of the form will be refreshed.
But it’s possible to mark some input fields as "noRefresh" to prevent the refresh, when the value of the field changes.
Configuration
Working with Configurator form requires code in two logics:
Configurator (form) logic - A separate logic (of Generic/Default type) which defines the form’s:
Sections - Each Section is returned as a result of one visible logic Element. Also, it is possible to define an Array or sections in one Element.
Input fields
Behavior / interactivity - How the Form reacts to the changes of values in the input fields. I.e., the code which dynamically (based on user inputs and selections) changes the list of input fields or their values.
"Main" logic (i.e., Quote, Dashboard, …)
Inserts a reference to the Configurator. The reference is usually rendered as a button.
The Configurator can be also _Inlined, i.e., the UI will reserve a block space on the screen (instead of rendering a button), and the Configurator form will render in that area.
Reads the values (entered/selected by the user) from the Form. Because the form has many input fields, the values are returned as a Map.
Uses the collected values for calculation.
The Configurator logic does not use Input Generation execution mode to collect the inputs and sections. It always executes in a regular execution, when the Form needs to refresh its sections and inputs.
"Hello World" Sample
Configurator logic - build the form with one section and one input
// define a Section
def section = api.createConfiguratorEntry()
// add one dropdown input field
section.createParameter(InputType.OPTION, "Meat")
.setValueOptions("Beef", "Lamb", "Pork")
.setRequired(true)
//return the Section definition. The logic Element containing this code must have DisplayMode set to Everywhere
return section
Main logic (e.g., Quote, Dashboard, etc) - insert a reference to Configurator
if (api.isInputGenerationExecution()) {
//insert the reference to the Configurator
api.inputBuilderFactory()
.createConfiguratorInputBuilder("<configurator_input_name>",
"<configurator_logic_name>",false)
.setLabel("Configure the Product") //❶
.getInput() //❷
}
❶ Set the label of the button, which opens the Configurator.
❷ This creates the Button which opens the Configurator form.The button works technically an input field, so the values entered by user in the Configurator form can be later read in the main logic the same way as any other input value.
Main logic - reading a value returned by Configurator
input["<configurator_input_name>"]?.Meat //❶
❶ The values of configurator form are available all together in one Map.This Map is provided as input field value, where the name of the input field is the one provided during call of api.configurator()
.In this case, we’re reading only the value of Meat input field from the Configurator form.
Interactive Form Sample
Many times you need some of the form’s input fields to appear depending on a value selected by the user in another input field. That’s why anytime, when the user makes some selection (or enters manually a value) in some input fields, the Configurator logic is executed, and the whole Form is rebuilt.
In the following sample the form will show only one dropdown input at the beginning. Once the user selects "Beef", the form will refresh (the Configurator logic will run again) and this time the logic will build two inputs. So now the user will see two inputs.
Configurator logic - element "Meat"
// define a Section
def section = api.createConfiguratorEntry()
// add one dropdown input field
section.createParameter(InputType.OPTION, "Meat")
.setValueOptions("Beef", "Lamb", "Pork")
.setRequired(true)
//return the Section definition. The logic Element containing this code must have DisplayMode set to Everywhere
return section
Configurator logic - element "Weight"
if (input.Meat == "Beef") {
/* when the value of input field "Meat" will not be "Beef", we will not build the "Weight" section neither the input field, so it will simply not appear on the screen at all. */
def section = api.createConfiguratorEntry()
section.createParameter(InputType.USERENTRY, "Weight")
return section
}
Error Messaging in the Form
Each Section can have a Message, which you can use for various purposes but it’s handy when you need to show an error message to the user while they use the Form. The Message can accept a piece of HTML, so you can style it as you need.
Configurator logic - use Message to display error to user
def section = api.createConfiguratorEntry()
def weightInput = section.createParameter(InputType.USERENTRY, "Weight")
if (weightInput.getValue() < 3) {
section.setMessage("<div style='color:red;'>error message: Weight must be at least 3kg</div>")
}
return section
Testing of the Configurator Form
The Configurator logic is, in principle, a lot different from other pricing logics:
It does not use the Input Generation mode to collect the input fields - instead it builds the form’s sections and the inputs differently.
The content of the form is refreshed each time when the user makes a change of any input field in the form. I.e., the system triggers recalculation of the Configurator’s logic, which will produce a brand new list of sections with inputs.
All that makes the testing somewhat different from a normal calculation logic, like Price List line or Quote line.
You have several options to test:
Directly in Pricefx UI (with both Configurator and Main logics deployed)
You will deploy both - Main and Configurator - logics to the partition and test as if you would be using it as a regular user.
In Studio via the Main logic (with the Configurator logic deployed)
You will deploy the Configurator logic to the partition, and then in open the Main logic in Studio, and test the Configurator in the Parameters tab (remember to click Generate parameters first).
In Studio, using additional code to simulate the inputs from user
You need to add an additional element (with code used only in DebugMode) to the Configurator logic, which will create the input fields definitions to simulate the inputs of the Form. Then you can test the Configurator logic directly from Studio without even deploying it.
Other Useful Code Samples
Add reference to Configurator to Header/Root folder
if (quoteProcessor.isPrePhase()) {
def configuratorDefinition = api.inputBuilderFactory()
createConfiguratorInputBuilder(
"<configurator_input_name>",
"<configurator_logic_name>",
false
)
.setLabel("<configurator_input_label>")
.buildMap()
quoteProcessor.addOrUpdateInput("ROOT", configuratorDefinition)
}
Passing initial values from the Main logic to Configurator logic
if (api.isInputGenerationExecution()) {
api.inputBuilderFactory()
.createConfiguratorInputBuilder("<configurator_input_name>",
"<configurator_logic_name>",
false)
.setLabel("Configure the Product")
// set initial values of the inputs in Configurator form
.setValue(["<cfg_input_name>" : "<cfg_input_value>"])
.getInput()
}
References
Documentation
Groovy API
Knowledge Base
Found an issue in documentation? Write to us.