Tutorial 20: Managing Screen Navigation in Formspider

This tutorial explains how to control the application flow by managing screen navigation in a Forsmpider Application. While the notion of application flow compromises many other diverse actions such as showing/hiding windows, LOVs, alerts etc. you will concentrate to the must fundamental element of the application flow; screen navigation meaning showing and hiding Formspider panels.

In this tutorial you will create a basic wizard. You will discover how change or remove displayed panels existing inside of other panels or even inside of a mainFrame.

Planning Application Flow

Your wizard’s flow is presented in the following diagram;


Application Flow

Your wizard will contain three main screens represented with “Start Wizard”, “Step 1” and “Step 2” shapes. Also you can notice that the “Step 2” screen contains a sub-screen named “Details” which can be optionally added inside of it at run time. Each of these screens corresponds to Formspider panels.

“Start”, “Next” and “Back” arrows are the actions representing direction of navigation between these screens meaning that which screen will be displayed in response of the action specified.

Having this diagram on your hand, you will start by creating the user interface.

Creating User Interface

As a first step, you have to create an application and your wizard’s panels. Then you will create actions for implementing the flow logic by changing or removing displayed panels in the wizard at runtime. Let’s start by creating the application.

Open Formspider IDE and click “New Application” under the “File” menu. The “New Application” dialog will show up. Enter “Wizard” as the name of the application and “HR” as its Datasource Schema name.  If you are using Formspider Online, you do not need to enter database schema name since your account is already configured to use your online database. Leave other fields empty and click “OK”. This creates the “Wizard” application with a default mainframe (called “mainFrame”) and a default panel (called “mainPanel”).

You will use “mainPanel” as the “Start Wizard” screen. This panel will simply contain a button labeled “Start Wizard” which will navigate the user to “Step 1” screen when pressed. To accomplish this double click the “mainPanel” under the “Panels” node of the “Containers” navigation tree to open it in the editor. Add a button labeled “Start Wizard” as shown below;

<panel>
  <tableLayout cellSpacing="10">
    <row>
      <cell hAlign="Center" vAlign="Center" childWidth="100" childHeight="20">
        <button label="Start Wizard"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Next, you will create a panel which will contain “Next” and “Back” buttons of your wizard. To achieve this, Expand the “Containers” accordion Panel, select the “Panels” node in the navigation tree and click the “+” button to create a new Simple Panel. Alternatively, you may right click the “Panels” node and select the “New” menu item from the pop-up menu. The “New Panel” dialog will show up. Enter “wizardButtons” as the name of the panel. Click “OK” to create and open the panel in the Editor.


Creating “wizardButtons” panel

Add two buttons labeled “Back” and “Next” in your “wizardButtons” panel.

<panel>
  <tableLayout>
    <row height="20">
      <cell hAlign="Right" vAlign="Full" childWidth="100">
        <button label="Back"/>
      </cell>
      <cell width="100" hAlign="Full" vAlign="Full">
        <button label="Next"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Next, you will create a panel which will contain your “wizardButtons” panel and where “Step 1” and “Step 2” screens of your wizard will be displayed. Create a new panel again and enter “wizardContainer” as the name of the panel. Click “OK” to create and open the panel in the Editor.

Add a first cell named “wizardContainer_center”, this is where your “Step 1” and “Step 2” screens will be displayed. Since its content will be change dynamically at run time you don’t have to include a panel in this cell at the design time. Also you will add a second cell at the bottom of this first one and include your “wizardButtons” panel in the “wizardContainer” panel for displaying “Next” and “Back” buttons. Remember that “Next” and “Back” buttons will be displayed statically during the usage of your wizard.

<panel>
  <borderLayout>
    <cell docking="Center" name="wizardContainer_center"/>
    <cell docking="South" height="20">
      <include panelName="wizardButtons"/>
    </cell>
  </borderLayout>
</panel>

As the final step of user interface implementation, you will create “Step 1”, “Step 2” and “Details” screens.

Create a new panel and enter “wizardStep1” as the name of the panel. This panel corresponds “Step 1” screen of your flow diagram. Add a textLabel for displaying a message. Your panel XML should look like;

<panel>
  <tableLayout cellSpacing="10">
    <row height="20">
      <cell hAlign="Full" vAlign="Full">
        <textLabel label="Welcome to the wizard, please click Next to proceed..."/>
      </cell>
    </row>
  </tableLayout>
</panel>

Create another panel and enter “wizardStep2” as the name of the panel. This panel corresponds “Step 2” screen of your flow diagram. You will add a textLabel for displaying some message and a button which will behave like a toggle button for adding the detail screen into this panel or removing it from this panel. Notice that there is an empty cell named “wizardStep2_details” between the textLabel and the button where “Details” screen will be added at run time. Your panel XML will look like;

<panel>
  <tableLayout cellSpacing="10">
    <row heightPolicy="Dynamic">
      <cell hAlign="Full" vAlign="Top">
        <textLabel label="Click Show Details button for more information or click Next to complete the wizard" text-align="Left"/>
      </cell>
    </row>
    <row>
      <cell name="wizardStep2_details"/>
    </row>
    <row>
      <cell hAlign="Right" vAlign="Bottom" childWidth="100" childHeight="20">
        <button name="details" label="Show Details"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Finally you will create a panel corresponding to “Details” screen of your flow diagram. Create a new panel from Formspide IDE and enter “wizardStep2Details” as the name of the panel. You will add a sample textLabel inside of this panel;

<panel>
  <tableLayout>
    <row heightPolicy="Dynamic">
      <cell hAlign="Full" vAlign="Full">
        <textLabel label="This sample wizard is prepared to demonstrate basic screen navigation in Formspider" text-align="Left"/>
      </cell>
    </row>
  </tableLayout>
</panel>

With this final step, you are completed the creation of every screen represented in your flow diagram. Next, you have to implement the application flow by developing a screen navigation logic.

Implementing Application Flow

Before starting the implementation of the application flow run your application. You will see that “Start Wizard” screen is displayed. When you clicked “Start Wizard” button, nothing happens.


Pressing “Start Wizard” button is useless at this point

Following your flow diagram you should display “Step 1” screen when “Start Wizard” button is pressed. So you have to create a Formspider action which will be fired when “Start Wizard” button is pressed and which causes “Step 1” screen to be displayed in the mainframe.

In your datasource schema, create a package called “wizard_pkg” and open your newly created “wizard_pkg” package in your favorite PL/SQL Editor. Add a procedure named “startWizard” and ensure that the procedure is exposed in the package specification. This procedure calls the api_panel.addpanel to display the “wizardStep1” panel in “wizardContainer_center” cell of the “wizardContainer” panel. Then you will use api_frame.addpanel for displaying “wizardContainer” panel in the “mainframe”. Notice that in order to use in API calls, you should assign a name to the cell of the mainframe in which you will add “wizardContainer” panel. To accomplish this open “mainFrame” and enter “mainframe_center” as the name of the cell in which “wizardContainer” will be added;

<mainframe title="Wizard" width="500" height="500">
  <borderLayout>
    <cell docking="Center" name="mainframe_center">
      <include panelName="mainPanel"/>
    </cell>
  </borderLayout>
</mainframe>
procedure startWizard is
begin
  api_panel.addpanel('wizardContainer', 'wizardContainer_center', 'wizardStep1');
  api_frame.addpanel('mainFrame', 'mainframe_center', 'wizardContainer');
end;

In Formspider IDE expand the “Actions” accordion, select the “Actions” node, click the “+” button to create a new action. Alternatively you may right click the “Actions” node and select “New” from the pop-up menu. The “New Action” dialog will show up. Enter “startWizard” as the action name and “wizard_pkg.startWizard” as the procedure. Click “OK” to save your action.


Creating “startWizard” action

Double-click and open the “mainPanel” in the editor. Add a buttonPress event to the “Start Wizard” button and call the “startWizard” action;

<panel>
  <tableLayout cellSpacing="10">
    <row>
      <cell hAlign="Center" vAlign="Center" childWidth="100" childHeight="20">
        <button label="Start Wizard">
          <events>
            <buttonPress action="startWizard"/>
          </events>
        </button>
      </cell>
    </row>
  </tableLayout>
</panel>

Run your application and press “Start Wizard” button again. This time you will see that “Step 1” screen is displayed on the screen.


“Step 1” screen displayed

Next you will create the actions which will be used in “Next” and “Back” buttons of your wizard. Open “wizard_pkg” package and create a procedure named “wizardNext” which will be used when “Next” button is pressed.

procedure wizardNext is
  v_wizardCenterCellContent_r api_application.t_object;
begin
  v_wizardCenterCellContent_r := api_panel.getCellContent('wizardContainer', 'wizardContainer_center');
  case v_wizardCenterCellContent_r.name_tx
    when 'wizardStep1' then
      api_panel.addpanel('wizardContainer', 'wizardContainer_center', 'wizardStep2');
    when 'wizardStep2' then
      api_frame.addpanel('mainFrame', 'mainframe_center', 'mainPanel');
  end case;
end;

When “Next” button is pressed, you have to distinguish which screen ( “Step 1” or “Step 2”) is currently being displayed in the screen. To achieve this you use api_panel.getCellContent API for acquiring the name of the panel which is displayed in specified cell. If the currently displayed screen is “Step 1” (“wizardStep1″ panel) pressing “Next” button will navigate you to “Step 2” screen (“wizardStep2″ panel). If currently displayed screen is “Step 2” pressing “Next” button will navigate you to “Start Wizard” screen (“mainPanel” panel).

Then, create a procedure named “wizardBack” which will be used when “Back” button is pressed. This time if currently displayed screen is “Step 1” pressing “Back” button will navigate you to “Start Wizard” screen and if currently displayed screen is “Step 2” pressing “Back” button will navigate you to “Step 1” screen.

procedure wizardBack is
  v_wizardCenterCellContent_r api_application.t_object;
begin
  v_wizardCenterCellContent_r := api_panel.getCellContent('wizardContainer', 'wizardContainer_center');

  case v_wizardCenterCellContent_r.name_tx
    when 'wizardStep1' then
      api_frame.addpanel('mainFrame', 'mainframe_center', 'mainPanel');
    when 'wizardStep2' then
      api_panel.addpanel('wizardContainer', 'wizardContainer_center', 'wizardStep1');
  end case;
end;

Create a new action and enter “wizardNext” as the action name and “wizard_pkg.wizardNext” as the procedure. Click “OK” to save your action.

Create another action and enter “wizardBack” as the action name and “wizard_pkg.wizardBack” as the procedure. Click “OK” to save your action.

Double-click and open the “wizardButtons” in the editor. Add a buttonPress event to the “Next” and “Back” buttons and call the “wizardNext” and “wizardBack” actions;

<panel>
  <tableLayout>
    <row height="20">
      <cell hAlign="Right" vAlign="Full" childWidth="100">
        <button label="Back">
          <events>
            <buttonPress action="wizardBack"/>
          </events>
        </button>
      </cell>
      <cell width="100" hAlign="Full" vAlign="Full">
        <button label="Next">
          <events>
            <buttonPress action="wizardNext"/>
          </events>
        </button>
      </cell>
    </row>
  </tableLayout>
</panel>

Run your application again. Notice that the application flow is almost implemented since “Start Wizard”, “Next” and “Back” buttons are functioning as expected.

The last step of your implementation is displaying “Details” in “Step 2” screen when “Show Details” button is clicked and hiding it when the same button is clicked again.

In the “wizard_pkg” create a new procedure named “wizardDetails”. In this procedure you will use api_panel.addPanel for displaying “Details” on the “Step 2” screen and api_panel.removePanel for removing “Details” from “Step 2” screen. You will decide if you have to add or remove “Details” screen by checking “Show Details” button‘s label.

procedure wizardDetails is
  v_detailButtonLabel_tx varchar2(4000);
begin
  v_detailButtonLabel_tx := api_component.getlabel('wizardStep2.details');
  if v_detailButtonLabel_tx = 'Show Details' then
    api_panel.addpanel('wizardStep2', 'wizardStep2_details', 'wizardStep2Details');
    api_component.setlabel('wizardStep2.details', 'Hide Details');
  else
    api_panel.removepanel('wizardStep2', 'wizardStep2Details');
    api_component.setlabel('wizardStep2.details', 'Show Details');
  end if;
end;

Create a new action and enter “wizardDetails” as the action name and “wizard_pkg.wizardDetails” as the procedure. Click “OK” to save your action.

Double-click and open the “wizardStep2” panel in the editor. Add a buttonPress event to the “Show Details” button and call the “wizardDetails” action;

<panel>
  <tableLayout cellSpacing="10">
    <row heightPolicy="Dynamic">
      <cell hAlign="Full" vAlign="Top">
        <textLabel label="Click Show Details button for more information or click Next to complete the wizard" text-align="Left"/>
      </cell>
    </row>
    <row>
      <cell name="wizardStep2_details"/>
    </row>
    <row>
      <cell hAlign="Right" vAlign="Bottom" childWidth="100" childHeight="20">
        <button name="details" label="Show Details">
          <events>
            <buttonPress action="wizardDetails"/>
          </events>
        </button>
      </cell>
    </row>
  </tableLayout>
</panel>

Run your application, navigate to “Step 2” screen and press “Show Details” button. You will see that “Details” is appeared on the screen and the button‘s label is set to “Hide Details”. When you pressed the button again you will see that “Details” is removed.


“Details” screen is displayed