Nested forms

Nested forms are forms within forms. Simian GUI supports nesting forms and provides utilities to manage forms that are nested one level deep. By toggling the visibility of the nested forms, the user interface can be separated into multiple pages. When using nested forms to group components, the submission data follows the same nesting structure (see Submission data).

Form and Form

Simian GUI has two Form classes:

  1. Form: This is the application form, the top level of the user interface.
  2. component.Form: This is a nested form, which is used as a component in the application form.

Although they both refer to the same type of form eventually, the properties and data associated with both classes are different.

Initialization

A nested form can be added to the application form in gui_init in a similar fashion as any other component.

nestedForm = component.Form(nestedFormKey, formObj)

However, the recommended method to add nested forms is addNestedForms:

formObj.addNestedForms(formKeys, createFcns, inputs, targetComponent)

where

  • formObj is the application Form object.
  • formKeys is an list/array of strings that are used as keys for the nested forms.
  • createFcns is a list of Callables (Python) or an array of function handles (MATLAB). Each of the functions is called to fill the corresponding nested form. The functions must accept their nested form object as first input argument, and the corresponding (optional) inputs. In the function components can be added to the nested form object.
  • inputs is a list of inputs (Python) or a cell array (MATLAB) to be used in the createFcns. This allows you to use the same createFcn more than once, but with different parameters.
  • targetComponent is the component to add the nested forms to. This input is optional and when no component is specified, the nested forms are added to the application Form.

The first nested form will be visible on initialization, while the others are hidden. The benefits of using this method are:

  • Manages switching behaviour (showing one nested form and hiding the others).
  • Less boilerplate code.

Note that you can only use the addNestedForms method once per application.

An example of how it can be used is given below.

form_defs = [ 
    # Key                       Create function                     Inputs
    ["mainForm",                guiLibrary.createMain,              []],
    ["inputForm",               guiLibrary.createInputPhase,        []],
    ["swapExemptionForm",       guiLibrary.createSwapExclusion,     []],
    ["createPhaseAsset",        guiLibrary.createCreatePhase,       ["Asset"]],
    ["createPhaseLiability",    guiLibrary.createCreatePhase,       ["Liability"]],
    ["testPhaseAsset",          guiLibrary.createTestPhase,         ["Asset"]],
    ["testPhaseLiability",      guiLibrary.createTestPhase,         ["Liability"]],
    ]
    
appForm.addNestedForms(*zip(*form_defs))
formDefs = {
    % Key                       Create function                     Inputs
    "mainForm"                  @guiLibrary.createMain              {}
    "inputForm"                 @guiLibrary.createInputPhase        {}
    "swapExemptionForm"         @guiLibrary.createSwapExclusion     {}
    "createPhaseAsset"          @guiLibrary.createCreatePhase       {"Asset"}
    "createPhaseLiability"      @guiLibrary.createCreatePhase       {"Liability"}
    "testPhaseAsset"            @guiLibrary.createTestPhase         {"Asset"}
    "testPhaseLiability"        @guiLibrary.createTestPhase         {"Liability"}
    };

appForm.addNestedForms([formDefs{:, 1}], formDefs(:, 2), formDefs(:, 3));

This creates seven nested forms, the first of which will be visible after initializing the application.

Switching Forms

For forms that have been added to the application using addNestedForms it is possible to switch between the forms using switchForms in gui_event. After event handling has completed, the selected form (identified by its key) will be displayed. Other nested forms will be hidden.

utils.switchForms(payload, "inputForm")
payload = utils.switchForms(payload, "inputForm");

The key of the currently visible form can be found as follows (with "currentFormKey" always the same):

current_form_key = utils.getSubmissionData(payload, "currentFormKey")
currentFormKey = utils.getSubmissionData(payload, "currentFormKey");

You can check if a given form is the nested form currently shown by using:

isShown = utils.isCurrentForm(payload, formKey)