Create a Form Logic
-
Create a form logic (defined as
formin JSON) and name it after the calculation logic, using the_Formsuffix. -
Create an element, for example
Init, and set Calculation context toinit. -
Link the new form logic to the pricing logic by using the
Form logicfield (formFormulaNamein JSON).
Convert Static Inputs
If a calculation logic had inputs (line item pricing logics, dashboard logics, etc.), it included elements for input generation mode (previously syntax check mode). This logic now moves to a form logic, init mode (= Calculation context of an element).
-
Remove all code inside the
if (api.isInputGenerationExecution())orif (api.isSyntaxCheck())blocks of calculation logic elements. Move it to an element of the created form logic and set the Calculation context toinit. -
Remove the code block in the element marking the end of input generation mode (typically called “AbortInputGeneration” or “AbortSyntaxCheck”):
Groovyif (api.isInputGenerationExecution()) { api.abortCalculation() }or
Groovyif (api.isSyntaxCheck()) { api.abortCalculation() }If no other code exists, remove this element entirely.
-
In the form logic, replace
api.inputBuilderFactory()calls with a variableformreferencingFormInitAPI. The following methods are unsupported:-
Replace calls to
createConfiguratorInputBuilder(), api.configurator(), api.inlineConfigurator()with the configurator logic content - see the next section. -
Remove
createRowLayout()andcreateCollapseLayout(). These input types arranged inner inputs in a row or collapsible panel; now layouts handle this. Keep only the inner inputs. -
Currently,
createConfiguratorTable()is unsupported. UsecreateInputMatrix()instead. Special actions for Input matrix will be introduced in 17.1.
-
-
Replace
AbstractInputBuilder.getInput()calls withAbstractInputBuilder.buildFormInput()
Convert Configurator Logics
Move the creation of initial inputs from the configurator logic to the form logic element with Calculation context = init. Initial inputs are those generated without passing values to the configurator logic (as if def input = [:]).
Replace the call AbstractInputBuilder.addToConfiguratorEntry(ce) with AbstractInputBuilder.buildFormInput().
Convert Header Logic Inputs
The CLIC header logic creates or updates inputs for the header or line items.
Header inputs should now be populated by form logic.
Replace occurrences of
-
quoteProcessor.addOrUpdateInput(contextParameter) -
quoteProcessor.addOrUpdateInput("ROOT", contextParameter) -
cProcessor.addOrUpdateInput(contextParameter) -
cProcessor.addOrUpdateInput("ROOT", contextParameter) -
raProcessor.addOrUpdateInput(contextParameter) -
raProcessor.addOrUpdateInput("ROOT", contextParameter) -
customFormProcessor.addOrUpdateInput(contextParameter) -
customFormProcessor.addOrUpdateInput("ROOT", contextParameter) -
AbstractInputBuilder.buildContextParameter(ce)
Call the root element in form logic with Calculation context = init and create an input using the corresponding form input builder.
Adjust Option, Options and Radio Inputs
Inputs Option, Options, and Radio have value options provided via these methods:
-
OptionInputBuilder.setOptions(valueOptions) -
api.option(inputName, valueOptions)
For static inputs, this can cause performance issues, especially in CLIC modules where quote objects become large because each line item stores all inputs and their value options.
Form logic allows value options to populate dynamically via asynchronous calls. This is recommended when there are more than 10 value options.
Create an element named, for example, ValueOptions in the form logic with Calculation context set to valueOptions. Implement the case of the switch for each input requiring value options:
switch (form.sourceInputName()) {
case "<input_name>": // replace <input_name> with a real element name
// place the code for populating the value options here (typically data queries)
break
}
Row and Collapsible Inputs
The methods creating Row and Collapsible inputs
-
createRowLayout(inputName) -
createCollapseLayout(inputName)
create a fake input that only contains inner inputs.
In forms, these fake inputs are unsupported; instead, layout objects serve this purpose. Consider this legacy code:
api.inputBuilderFactory()
.createRowLayout("Row")
.addInput(
api.inputBuilderFactory()
.createStringUserEntry("Width")
.buildContextParameter())
.addInput(
api.inputBuilderFactory()
.createStringUserEntry("Height")
.buildContextParameter())
.getInput() // or addToConfiguratorEntry() or buildContextParameter()
The solution in forms is:
def row = layout.createRow("MyRow")
form.createUserEntry("Width")
.addToFormLayout(row)
form.createUserEntry("Height")
.addToFormLayout(row)
layout.addChild(row)
Implement Actions
Identify which user interactions modify form inputs by changing properties, affecting value options, or adding or removing inputs.
Create an element in the form logic with Calculation context = action. For each action, implement the case of the switch for every input requiring value options:
switch (form.sourceInputName()) {
case "<input_name>": // replace <input_name> with a real element name
// place the code FormActionApi calls that modify the inputs of the form
break
}