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).

Limitation: When nested forms are used, all controls should be added to the nested forms. Adding controls to the main form may cause errors when events are processed. In a future release having nested forms and controls in the main form will be supported.

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 guiInit 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)

where

  • formObj is the Form object.
  • formKeys is an array/list of keys, one for each of the nested forms to create.
  • createFcns is an array of function handles (MATLAB) or a list of function names including namespace (Python). Each of these is called to initialize a nested form. The input to each of them is the nested form object and optionally, the inputs provided.
  • inputs is a cell array (MATLAB) or a list of inputs (Python) to send to the createFcns. This lets you call the same createFcn multiple times, but with different parameters.

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

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

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

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));
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))

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 guiEvent. After event handling has completed, the selected form (identified by its key) will be displayed. Other nested forms will be hidden.

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

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

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

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

isShown = utils.isCurrentForm(payload, formKey)