This week, we are kicking off a weekly series of ‘how-to’ posts for InstallBuilder, our crossplatform installation tool. Each how-to will include detailed instructions, as well as downloadable XML examples and (in most cases) a video demonstrating the process. In this first installment, we’re going to cover how to create custom pages. InstallBuilder allows you to create multiple parameter pages: stringParameter, choiceParameter, booleanParameter… But what if you want a more customized page? Here is where parameterGroups come into play. parameterGroups allow you to define a list of parameters to be displayed in the same page and how to display them. This tutorial will be divided in 3 steps. First, we will design the page schema. In the second step, we will apply validations to fields. In the last step, we will perform actions based upon the user input.
First step:
For this example, we are going to collect information to configure a web application. The required fields will be:
Lets create a basic template of the page. In this code, we have listed the parameters inside an <actionGroup>:
<project>
<shortName>sample</shortName>
<version>1.0</version>
<parameterList>
<parameterGroup>
<name>configuration</name>
<title>Configuration</title>
<explanation>Configuration page</explanation>
<value></value>
<default></default>
<parameterList>
<stringParameter>
<name>username</name>
<description>Username</description>
<explanation>Administrator account username</explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<width>30</width>
</stringParameter>
<passwordParameter>
<name>password</name>
<description>Password</description>
<explanation>Addministrator account password</explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<descriptionRetype></descriptionRetype>
<width>20</width>
</passwordParameter>
<stringParameter>
<name>ipaddress</name>
<description>Web Server IP</description>
<explanation></explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<width>30</width>
</stringParameter>
<stringParameter>
<name>port</name>
<description>Web Server Port</description>
<explanation></explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<width>30</width>
</stringParameter>
<booleanParameter>
<name>advancedconfig</name>
<description>Enable advance</description>
<explanation>Would you like to perform an advance installation?</explanation>
<value></value>
<default></default>
<displayStyle>checkbox-left</displayStyle>
</booleanParameter>
<choiceParameter>
<name>dbmsserver</name>
<description>DBMS</description>
<explanation>Database server</explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<displayType>combobox</displayType>
<width>30</width>
<optionList>
<option>
<description>MySQL server</description>
<image></image>
<text>MySQL</text>
<value>mysql</value>
</option>
<option>
<description>PostgreSQL server</description>
<image></image>
<text>PostgreSQL</text>
<value>postgres</value>
</option>
</optionList>
</choiceParameter>
</parameterList>
</parameterGroup>
</parameterList>
</project>
Then, build and run.
Image 1:
This is obviously not the expected result. We can modify the height of the page but the result is not ideal:
<project>
...
<height>400</height>
...
</project>
Image 2:
As we said, this is better but still not the best it could be.
Using nested parameterGroups, we can use the <orientation> tag to modify the organization of the default parameters inside the parameter group from “vertical” to “horizontal”. Also, nested parameter groups allow us to group related fields (for example, username and password):
<parameterGroup>
<name>configuration</name>
<title>Configuration</title>
<explanation></explanation>
<value></value>
<default></default>
<parameterList>
<parameterGroup>
<name>adminaccount</name>
<title></title>
<explanation>Admin Account</explanation>
<orientation>horizontal</orientation>
<value></value>
<default></default>
<parameterList>
<stringParameter>
<name>username</name>
<description>Username</description>
<explanation></explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<width>20</width>
</stringParameter>
<passwordParameter>
<name>password</name>
<description>Password</description>
<explanation></explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<descriptionRetype></descriptionRetype>
<width>20</width>
</passwordParameter>
</parameterList>
</parameterGroup>
<parameterGroup>
<name>serveraddres</name>
<title></title>
<explanation>Server Address</explanation>
<orientation>horizontal</orientation>
<value></value>
<default></default>
<parameterList>
<stringParameter>
<name>ipaddress</name>
<description>IP and Port</description>
<explanation></explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<width>30</width>
</stringParameter>
<stringParameter>
<name>port</name>
<description>:</description>
<explanation></explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<width>5</width>
</stringParameter>
</parameterList>
</parameterGroup>
<booleanParameter>
<name>advancedconfig</name>
<description>Enable advance</description>
<explanation>Would you like to perform an advance installation?</explanation>
<value></value>
<default></default>
<displayStyle>checkbox-left</displayStyle>
</booleanParameter>
<choiceParameter>
<name>dbmsserver</name>
<description>DBMS</description>
<explanation>Database server</explanation>
<value></value>
<default></default>
<allowEmptyValue>1</allowEmptyValue>
<displayType>combobox</displayType>
<width>30</width>
<optionList>
<option>
<description>MySQL server</description>
<image></image>
<text>MySQL</text>
<value>mysql</value>
</option>
<option>
<description>PostgreSQL server</description>
<image></image>
<text>PostgreSQL</text>
<value>postgres</value>
</option>
</optionList>
</choiceParameter>
</parameterList>
</parameterGroup>
Image 3:
We now have the desired result.
Let’s continue to step 2, validations.
Step 2: At this point, a user could leave some required fields blank or provide a nonnumeric value for the port. We need to validate the information provided and, in the event that it is not valid, ask for the information again.
Username and password: We need a username, but we want to allow the password field to be blank . We will include a pop-up to warn the user. To require a non-empty value, we just need to set <allowEmptyValue>0</allowEmptyValue> in the desired parameter. For more complex validations, such as launching a pop-up to warn the user, we need a <validationActionList>:
<passwordParameter>
<name>password</name>
...
<!-- In a validationActionList you can execute any desired action -->
<validationActionList>
<showQuestion text="Are you sure you want to provide an empty password?" variable="continue" >
<ruleList>
<compareText text="${password}" logic="equals" value=""/>
</ruleList>
</showQuestion>
<!-- The next_page built-in variable controls the intallation flow at runtime -->
<setInstallerVariable name="next_page" value="configuration">
<ruleList>
<compareText text="${continue}" logic="equals" value="no"/>
</ruleList>
</setInstallerVariable>
</validationActionList>
</passwordParameter>
IP and port: We could do a lot of validations here, but lets limit them to require a pseudo valid IP (four three digit numbers separated by periods) and a valid port that is not in use.
<parameterGroup>
<name>serveraddres</name>
<title></title>
<explanation>Server Address</explanation>
<orientation>horizontal</orientation>
...
<parameterList>
<stringParameter>
<name>ipaddress</name>
<description>IP and Port</description>
...
<validationActionList>
<setInstallerVariableFromRegEx text="${ipaddress}" pattern="^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$" substitution="valid" name="result"/>
<actionGroup>
<actionList>
<throwError text="This not seems to be a valid IP addres"/>
</actionList>
<ruleList>
<compareText text="${result}" logic="does_not_equal" value="valid"/>
</ruleList>
</actionGroup>
</validationActionList>
</stringParameter>
<stringParameter>
<name>port</name>
<description>:</description>
...
<width>5</width>
<validationActionList>
<throwError text="Cannot bind to the selected port. Please choose another one.">
<ruleList>
<portTest condition="cannot_bind" port="${port}"/>
</ruleList>
</throwError>
</validationActionList>
</stringParameter>
</parameterList>
</parameterGroup>
As the rest of the parameters are constrained by the installer and cannot contain incorrect values, we do not need to perform any more validations.
Step 3:
Now, once we have all the needed information and we are sure it is correct, we can perform some actions with it before the next page appears. For example, based on the “Advanced Installation” booleanParameter, we could make visible a by default hidden page.
Lets assume the advance configuration is the installation directory. If the parameter is checked, the installation directory will be visible. Otherwise, it will not be displayed.
<!– the <ask> tag of a parameter controls if it will be shown or not. When a parameter
is not shown its preShowPage and postShowPage won’t be executed –>
<directoryParameter>
<name>installdir</name>
<description>Installer.Parameter.installdir.description</description>
<explanation>Installer.Parameter.installdir.explanation</explanation>
<!– The insertAfter and insertBefore tags define
in which position a parameter will be shown –>
<insertAfter>configuration</insertAfter>
<default>${platform_install_prefix}/${product_shortname}-${product_version}</default>
<ask>0</ask>
</directoryParameter>
As we have set by default <ask>0</ask>, this parameter will be hidden and the user would be unable to change it.
Getting back to our custom page, we could use the <postShowPageActionList> to show the installdir parameter:
<parameterGroup>
<name>configuration</name>
<title>Configuration</title>
...
<parameterList>
...
</parameterList>
<!-- Using the notation below we can modify any parameter property -->
<postShowPageActionList>
<setInstallerVariable name="project.parameter(installdir).ask" value="1" >
<ruleList>
<isTrue value="${advancedconfig}"/>
</ruleList>
</setInstallerVariable>
</postShowPageActionList>
</parameterGroup>
We now have a complete custom page.
You can download the XML project file from the InstallBuilder website
We have also made a video demonstrating the process via the GUI:
For an extensive list of rules and actions to use for custom pages, please refer to the InstallBuilder reference documentation. Also, these articles in our KnowledgeBase provide additional information on the topics mentioned in the article:
next_page
built-in variable: How to Control the Flow of Pages