01 - Build A Dynamic List
01 - Build A Dynamic List
In order to complete the tutorial, you will need an Appian 19.3 (or
later) practice environment.
This exercise is the second exercise in the Advanced Interfaces Exercise Series.
The four exercises accompany our courses Interfaces 102 & Interfaces 103:
Exercises build upon each other, so please keep the app and objects created in each
exercise. If you are using the trial version of Appian and plan to continue with
exercises in a different environment, remember to export the ADV Interfaces Practice
app before the expiration of your trial site.
In this exercise, we will build a form containing a Dynamic Radio Buttons Component. When
done, your interface will look like this:
Our radio buttons will be dynamically populated by the address values queried from a database.
In this exercise, we will learn how to use the a!forEach looping function to apply a specific
structure to all queried addresses. We will also learn how to use the conditional if() function to
display the unit field only if the unit information is available. We will configure our form to save
the user-selected address into the rule input. The subsequent “Build a Dynamic Link
Component” and “Build an Editable Grid” exercises will be built using the dynamic list interface
that you will create in this exercise.
If at any point you need to double-check your expression, scroll to the Appendix at the end of
this exercise. Please note that the steps in this exercise are written with the Appian trial
environment in mind. If you use a different environment, you might need to adjust your steps.
Let’s get started!
Before we can create our dynamic list interface, we need to create several Getting Started
objects. Below is the list of the objects we will create:
1. Let’s create an address table in our database. If you are working in the Appian trial
environment, log into your Appian environment, and click the Navigation Menu
in the top right corner. Click Cloud Database. If your environment is different, navigate
to your specific database location.
2. Notice that you can expand the view of tables by clicking the + sign next to Appian
(located in the left-hand menu). If you work in a different environment, you might not
have Appian, but a different name for tables. Next, click the SQL tab in the top menu.
Copy and paste the below SQL code into the canvas:
shipping_address varchar(100),
unit_number int(5),
city varchar(100),
state_or_province varchar(2),
postal_code int(5));
4. To check that your SQL code imported correctly, click the address in the table tree on
the left. You will see that your table (currently empty) has 6 fields:
5. Now let’s populate our address table with some sample data. Click the SQL tab, and
copy and paste the below SQL snippet into the canvas. Click Go to upload the data.
Once again, return to your Appian environment. Now we will create two groups, the CDT, and
Data Store. Please remember that groups are needed to configure security of Appian objects. In
any app, you will have at least two groups: All Users (the parent group for all other groups) and
All Administrators. In this exercise, we add the groups only to the Data Store object to save
time. In a real life app, you will be configuring security and adding groups to all objects.
1. Click to access the application ADV Interface Practice application created in the
previous exercise. Click New, and then select G
roup. In the dialog box, title the group
ADV All Users, add a brief description, and click Create. This will be the parent group
for all other groups. In the same manner, create the ADV All Administrators group, but
designate ADV All Users as a parent group.
3. In the Create Data Type dialog box, edit the following fields:
b. Name your CDT ADV_Address, and add a description. Click the Key Icon for
the addressId field, and check that the Primary Key is set to auto-increment (the
check box next to Auto-generate must be checked). Click Create.
5. In the next dialog box, define security by adding user groups to this object. Add ADV All
Users with the Viewer permission level, and add ADV Administrators with the
Administrator permission level.
6. In the next screen, double-check that the correct data source is selected, and click Add
Entity. Search to locate the ADV_Address, and then click Save:
Scroll down, click Verify, and finally click Save and Publish. You can now close the tab
with this object.
In order for an expression rule to query the data from our database, we need to create a
constant pointing to the Data Store Entity address. Follow the steps below to create the
constant and the expression rule:
Follow Appian’s best practices for naming objects. By adding DSE into the name of our
constant, we let other developers know that this constant points to a data store entity.
2. Now that we have a constant, let's create a folder for expressions and an expression rule
to query the address data from the database. Click New, and select Folder. Title the
folder ADV Expression Rules, add a brief description (“Folder to store expressions for
the ADV app), and select ADV Rules and Constants as its parent folder.
3. Next, click New, and select Expression Rule. Name your expression
ADV_getAddresses, and store it in the ADV Expression Rules folder.
4. Add the rule input to your expression, called addressId of type integer:
a!localVariables(
local!queryResults:
a!queryEntity(
entity: cons!ADV_DSE_ADDRESS,
query: a!query(
paginginfo: a!pagingInfo(1, -1),
logicalExpression: a!queryLogicalExpression(
operator: "AND",
ignoreFiltersWithEmptyValues: true,
filters: {
a!queryFilter(
field: "addressId",
operator: "in",
value: ri!addressId
),
}
)
)
).data,
Note that this query declares a local variable local!queryResults, and then casts the
queried data to an array of the ADV_Address CDT. We are doing this because the
query entity returns a data subset by default. This will cause a problem later when we set
up the interface to save the selected address into the rule input ADV_Address. Casting
now will make our lives easier because the types of the queried address and the rule
input ADV_Address will match.
6. Save your expression, and then click the Test Rule button. Ensure that the query returns
the address data from the database.
In this part of the exercise, we will build the interface with the dynamic radio button component.
First, we will create a basic interface with the Radio Buttons element.Then we will make the
interface dynamic by configuring the following elements:
1. From the Appian designer, click New and select Interface. Title the interface
ADV_DynamicAddressList, add a simple description, and save it into the ADV
Interfaces folder.
3. In the canvas, change the label of the section layout from Section to Address.
4. Select the Radio Buttons component, and drag it to your Address section layout. In the
Component Configuration pane, change the Label Position to Hidden as the section
itself contains the needed label.
1. To add a new Rule input, press CTRL (Command o n Mac OS) + I to display the N
ew
Rule Input dialog box. Type address in the Name field, and start typing ADV_Address
in the Type field. Use the Autocomplete Feature to select ADV_Address.
2. To add a local variable, click the Expression Mode button. In the Expression Editor, fold
line one by clicking the down arrow next to the line number.
Place your cursor at the front of the block and press Enter.
3. In line one, start typing a!localVariables and press Enter to accept the autocomplete
suggestion. To enclose the folded expression within the a!localVariables function,
delete the close parenthesis. Then add a new line after the folded expression on line
two. Add the missing close parenthesis after the folded expression. You will notice that
the Address Section is displayed again in the Preview pane.
5. You will notice that at this point the interface will give an error. The error will state that
the interface cannot display because it expects a value for the variable
local!locationsList. Let’s supply this value directly from the Expression Editor. Earlier
we created an expression rule ADV_getAddresses to query addresses from a database
table. To call this expression rule, type rule! and start typing ADV_getAddresses. The
Autocomplete Function will automatically suggest this expression rule. Press Enter to
accept the suggestion.
6. At this point, you will see an error because the interface is expecting to receive a value
for the expression rule. Since we don’t have any values, let’s add a NULL value to the
expression rule. Click within the parenthesis after rule!ADV_getAddresses, and type:
7. Finally, let’s review the Local Variables tab (located in the right pane). Note that now we
can see the value of our newly defined local variable:
Now that we are done adding rule inputs and local variables to the interface, we need to
configure the Radio Buttons component. More specifically, we will need to add the address data
to the buttons by configuring their labels and values. Follow the steps below to complete these
configurations:
1. In the Interface Definition pane, unfold the section layout. Note that the choiceValues
parameter for the Radio Button field has the numbers 1 and 2 listed by default. Since
now we have a local variable that has the address data queried from the database table,
we can replace 1 and 2 with the values from our local variable.
To do so, delete the curly braces and the numbers 1 and 2 listed for the choiceLabels.
Type local!locationsList instead. Do the same thing for the choiceValues:
Currently, the choiceLabels contain the entire list of addresses from the query.
However, our addresses are not formatted, and we see both fields and labels. While this
contains all data, the look of our options is not user-friendly. Let’s change the formatting
to make our form more pleasant for the viewer.
To improve the look of our addresses, we will replace the local variable in the choiceLabels
parameter with the a!forEach function. The a!forEach function will help us to define the
structure of each address line. Complete the steps below:
2. Press Tab twice to indent (or use the Increase Indent button on the toolbar), and then
type a!forEach, and press Enter to accept the autocomplete value.
If you have an array of data that you need to loop through an expression, the a!forEach
function will suit your needs. In our interface, we will use a!forEach to create the row for each
address item. To make the a!forEach function work, we will need to provide Appian with two
parameters: 1) the items, and 2) an expression to loop them through.
A typical expression in the a!forEach function may draw on the following function variables:
4. Let’s define the items for the a!forEach function. Type i tems on the new line, and
accept the autocomplete to insert a colon. After the colon, start typing
local!locationsList. Press Enter to accept the autocomplete prompt. Add a comma,
and then press Enter to add a line.
6. In the Preview pane, observe the interface. Note that the formatting of the radio buttons
looks identical to what we had previously:
This is because the a!forEach function is iterating through each element in our
locationsList local variable, performing the expression for each element. In this case,
the expression is fv!item, which is simply the current item. To change the look of our
addresses, we will modify the formatting in the expression itself.
7. In order for our addresses to acquire a cleaner look, we will now modify our expression
by replacing fv!item (which represents the entire address object) with its elements:
● fv!item.shippingAddress
Correct punctuation is vital to Appian. In the steps that follow, we will be adding the
rest of the fv!item elements into our address. While this is not difficult, we will need to
use correct punctuation if we want Appian to understand and display our content
correctly. Let’s review the punctuation that we will use:
● We will use the ampersands to concatenate (or add) the elements to our
address.
● We will use quotation marks with the added space within to add space after
the ampersands.
For example, if you want to add another fv!item element and a space after the
shipping address, punctuate your expression as follows:
9. Our next address field is fv!item.unitNumber. Since not every address in the database
includes a unit, we will add the if() function to handle this condition. With if(), the unit
number will display only if the unit element includes a value.
The if () function is helpful when we want to create a conditional statement, where one
expression is returned if a statement is true, and another ‒ if a statement is false. For the
if () function to work, we need to define 3 parameters:
Note that when null values are passed to the condition parameter, they are considered
to be false.
10. After the ampersand (&) for the shipping address, press Enter, and type if. Accept the
autocomplete prompt. To check for our condition (whether the unit number is available),
we will use the isnull() function.
So, inside the parentheses of the if() function type isnull(fv!item.unitNumber), followed
by null (if the unit value is empty) and “ Unit #” & fv!item.unitNumber (if the unit value
is available). Your expression will look as follows:
Now, let’s examine the Preview pane. Your interface now should look like this:
● Use the open and close quotation marks (“ ”) to provide a blank text value
● Use the open and close curly braces ({ }) to indicate an empty list of values.
Want to see how these synonymous expressions work? Experiment by replacing the
NULL value in your interface with these two synonyms!
11. Finally, add the remaining fv!item elements into our expression. Our goal is to display
the city (followed with a comma and space) and the state (followed by a space and
postal code). One by one, add the rest of fv!item elements. After you are done, your
expression should look as follows:
Let’s examine the Preview pane once again. You will see that our dynamic list is now
neatly formatted:
Switch to the Design Mode, and select the Radio Buttons component. You will notice that the
Select Value and Save Selection To fields in the Component Configuration pane are blank.
Also notice that if you select a Radio Button, your selection will get cleared as soon as you click
away. This happens because at the moment our interface does not know which value to display,
and where it should be saved. Let’s change this situation by configuring the Selected Value and
Save Selection To fields.
3. Click Save Changes, and then click to select a radio button in the interface. Verify that
the selection is preserved after you click outside of the selection zone. Also, verify that
your selection is now saved into the address rule input:
At this point, you should have a better understanding of the steps required to build a dynamic
interface component. Before you advance to the next exercise in our series, skim through the
topics below. If any of these topics still seem fuzzy, review the steps in the exercise, and build
the interface once again, paying attention specifically to the sequencing and syntax of Appian
configurations.
● Add a query to the interface and use the queried data to populate the address radio
buttons.
● Use the looping and conditional functions a!forEach() and if() and function variable
fv!item to format each element in the array of the returned data.
● Save the selected address value into the rule input.
Before you go …
This is the second exercise in our Advanced Interfaces Exercise Series (and the
first exercise to accompany the Interfaces 103 course). If you plan to continue with
the remaining exercises that accompany the course “Interfaces 103: Build Dynamic
Interfaces,” make sure to keep the objects that you’ve created for the ADV application
thus far. We will reuse some objects in subsequent tutorials. If you are using the trial
version of Appian and plan to continue with exercises in a different environment,
remember to export the ADV app before the expiration of your trial site.
a!sectionLayout(
label: "Address",
contents: {
a!radioButtonField(
labelPosition: "COLLAPSED",
choiceLabels:
a!forEach(
items: local!locationsList,
& " " & fv!item.city & ", " & fv!item.stateOrProvince & " " &
fv!item.postalCode
),
choiceValues: local!locationsList,
value: ri!address,
saveInto: ri!address,
choiceLayout: "STACKED",
validations: {}