Skip to main content

Creating steps

Similar to a Page, grouping can be achieved by using the Step class. Other than with pages, with steps the developer can dictate the order of pages to be visited: the user is not able to move freely between pages but moves to the next/previous step with a next/previous button. Page and Step cannot be combined within a single parametrization.

A Step is defined in the parametrization similar to a Page. The labels of the next and previous buttons can be set per step:

from viktor.parametrization import ViktorParametrization, Step, TextField, NumberField


class Parametrization(ViktorParametrization):
step_1 = Step('Step 1 - without views')
step_1.input_1 = TextField('This is a text field')
step_1.input_2 = NumberField('This is a number field')

step_2 = Step('Step 2 - with views', views=['geometry_view', 'data_view'])
step_2.input_1 = TextField('This is a text field')
step_2.input_2 = NumberField('This is a number field')

Step 1 with no views

When navigating to step 2, you will see that the two views will be present:

Step 2 with a GeometryView and a DataView

Button labels

The labels of the previous and next buttons can be set per step:

Step('Step 2', previous_label='Go to step 1', next_label='Go to step 3')

Validation of user input

New in v13.7.0

When implementing the on_next argument, the corresponding function is called when a user clicks the 'next' button to move to the next step. This can be used to, for example, validate the input of the current active step. Please note that the validation function cannot take longer than 3 seconds!

from viktor.errors import UserError
from viktor.parametrization import ViktorParametrization, Step, NumberField


def validate_step_1(params, **kwargs):
if params.step_1.width > params.step_1.height:
raise UserError("The design is not feasible")


class Parametrization(ViktorParametrization):
step_1 = Step('Step 1', on_next=validate_step_1)
step_1.width = NumberField('Width')
step_1.height = NumberField('Height')

Generic constraints (e.g. min on a NumberField) are automatically validated by the platform. Additionally, fields can be marked as invalid.

tip

All individual kwargs can be added explicitly in the signature if needed:

def validate_step_1(params, entity_id, entity_name, workspace_id, **kwargs):
...

Disabling a step

New in v14.11.0

Disabling a Step can be done by setting the enabled argument, similar to hiding a field:

  • By using a BooleanField
Step("Step 2", enabled=Lookup("step_1.param_x"))
  • By using a callback function
def get_enabled(params, **kwargs):
return params.step_1.param_y > 5

Step("Step 2", enabled=get_enabled)
  • Depending on other field(s)
_step_enabled = And(
IsFalse(Lookup('step_1.param_x')),
IsEqual(Lookup('step_1.param_y'), 5)
)

step = Step("Step 2", enabled=_step_enabled)

When a step is disabled, it will be skipped when the user clicks the "next step" button. The step number will remain visible, as a visual cue that there is a skipped step.

In some cases you may have steps that depend on user input. For example, "Step 2(a)" for calculations about a stone house, and "Step 2(b)" for calculations about a glass house. In such cases, we recommend to merge them into one step (e.g. "Calculations") and use tab visibility to hide the tab/fields that you do not need, within the step. This will lead to a more consistent flow through the steps for the end user.

Adjust the parametrization width

New in v14.7.0

A separate parametrization width per Step can be defined by specifying the width argument:

class Parametrization(ViktorParametrization):
step_1 = Step("Step 1", width=30)
...
step_2 = Step("Step 2", width=70)
...

When the width is defined both on the Parametrization class and a Step, the width of the Step will take precendence while the global width is used for steps that have not defined a specific width. For more detail on the global parametrization width and rules with respect to a field's flex argument, please refer to this page.