# Dropdown Menus

## Introduction

Dropdown lists are a great way to allow a user to pick from a list of items, while keeping the UI elements to a bare minimum.

## Create your Dropdown

Start by creating a new Airkit application (or editing an existing one):

1. Once your application is open in [Studio](https://studio.airkit.com/), go to the Web Page or Container you’d like to add a dropdown to.&#x20;

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-ac4578e7609f3307eb4ab89a2dd152acb3499679%2Fcreating-a-dropdown-v1715-0.png?alt=media)

2. Click on the '**+**' button on your Web Page or Container to add elements to the card view, and select:\
   \*Container / Web Page → Dropdown List&#x20;

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-ddafd69b8243e6a9acafc02e7e7814680d7340bf%2Fcreating-a-dropdown-v1715-1.gif?alt=media)

Now that we have a dropdown, its possible to customize it's styling within **Inspector > Style**.

## Dropdown Customization

There are a lot of ways to style a dropdown which we won't go into full-detail here, but below is a simple example where the Arrow has been made blue with a grey background.

If you're interested in learning more about styling, we recommend looking at our documentation on [Themes and Control Variants](https://docs.airkit.ai/?q=working-with-themes-and-control-variants).

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-22b2f1140e95012d717c1b82aecf4ccfd9e72a5e%2Fcreating-a-dropdown-v1715-2.png?alt=media)

3. Let’s dive in! The main properties' sections for a Dropdown list are:

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-a6106ebd838cad7142015ba1667db52329aa964c%2Fcreating-a-dropdown-v1715-3.png?alt=media)

```
* Control Properties
* Data Binding
```

**Control Properties**\
In the control properties section you can set up the _variable_ you’ll be saving the selected option to (value) as well as the _text shown to the user_ when no option has been selected (placeholderText).&#x20;

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-b07e703d8dd3dcd118fc83c18cddffd984a8ef7c%2Fcreating-a-dropdown-v1715-4.png?alt=media)

`_variable_to_save.selection_to_` needs to be a valid variable i.e. it needs to exist within your application. If you are not yet sure of the _scope_ you need for your variable, it is ok to use _session_ while you build (not recommended for published apps): `session.variable_to_save.selection_to`

Please review your [variable scope](../../working-with-data/variable-scopes) to make sure you’re using the appropriate variable scope.

1. **Data Binding**\
   In the Data Binding section, you can control the data used to populate the dropdown list and how it’s displayed to the user.

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-1e9a5b57f00e9eb11bdefd021d50b14221d3dfd4%2Fcreating-a-dropdown-v1715-5.png?alt=media)

* **Data** is the List of items that will be shown as a list when opening the dropdown. You can hard-code a List or use a [_Data Flow_](../../studio/data-flows) to query an [_App Object_](../../studio/builder-bar/data-builder) and display a List. The above example displays contains a hard-coded List for the Dropdown.
* **Display Text** is the value that reflects _what_ will displayed.  In simple examples, the value should be "item" to reflect _each item_ of the Collection / List provided to the Dropdown.
* **Value Text** is the _value_ that is saved when the app user selects an item from the Dropdown List.
* **Selected** gives you the ability to control whether the value selected is displayed to the app user. This field evaluates an expression where if TRUE, will display the value to the app user.  For a more-detailed explanation, see [Dropdown List Control](../../web-controls/dropdown-list-web-control).

## Static and Dynamic Dropdown Lists

### Creating a Static Dropdown List

Option Lists are useful when the items in the list are known at the creation time of the app. For example, selecting a lead type for a new salesforce contact or selecting a t-shirt size on an ordering form. Let's build out the example to rate a book in the AirBooks app.

Start with a [Web Flow](../../studio/web-flows) with one page on it. Add a label of the large variant, set the text to "Enter Your Book Review:." Next, add a container with a label and a text input. Set the label equal to "Enter the book title." Add a new container with a label with the text "Select a rating." Next, add a Dropdown list under the picker option in the Add Control dialog.

With the dropdown selected, the inspector will have a section called _Data Binding_. This section is used to determine the items that will appear in the list and where the selected value will be stored. By default, when a dropdown is inserted into the Tree a variable is created to store the result. There are two options for dropdown list type: simple list, and custom expression. Simple list, also known as an option list, is where you configure the items in the UI.

Add five different items by clicking the + icon to the right of the options. Set the values to **1 Star, 2 Stars, 3 Stars, 4 Stars**, and **5 Starts**. In a simple list, when the user selects an option from the dropdown, that text value will be stored in the text variable.

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-51b8fe595f9072b077504f0095b0063409b724bc%2Fcreating-a-dropdown-v1715-6.png?alt=media)

### Creating a Dynamic Dropdown List

Whereas simple list drop-downs are great for known information, dynamic lists are great for use when the items in the list can be dynamically run generated at run time. These are also useful if the list will be populated from configuration information that may change over time. Let's say that in addition to letting the user rate the book, the user should be allowed to select the category of the book during the review.

Start by going to Data Builder and creating a new [App Object](../../working-with-data/airdata/airdata-app-objects). Title it "Genre", rename the property from **Name** to **genre\_title** and add options in Data Builder for the categories: "Youth", "Reference", "NonFiction", and "Mystery." Click save and click continue on the save dialog when it appears. It is simply saying that we are adding new data to the AirData Datastore attached to our app.

Go to [Connection Builder](../../studio/builder-bar/connection-builder) and add a new Data Flow named "AD - Get genres." Modify the first Data Operation to be of type "Object-Service." Select the app object _Genre_ from the dropdown. Make sure the type is QUERY. Click Run at the top of the step and confirm that the output contains the shelves you added above. Because the query run returns a complex object with a bunch of different options, add a transform step after the query. Set the body of the transform to:

```javascript
airData.results[*].genre_title
```

Return the result of the transform from the Data Flow.

```javascript
[  
  "Nonfiction",  
  "Mystery",  
  "Reference",  
  "Youth"  
]
```

Go to Web Builder and modify our book review page to add a container between Star Rating and the Review box. Add a label "Genre" and a dropdown list to the container. Instead of the simple option list, this box will be populated by the connection built above. Select the Web Page and add a variable called **genres** as a list of text.

With the Web Page still selected, go to the Actions tab in the inspector and add an action for Run Data Flow under the App Section in the Action Builder. Select _AD - Get genres_ from the dropdown and the output binding to **genres**.&#x20;

Select the dropdown list in the shelf container. Under _Data Binding_ look for the _Type of List_ option. Change it from "Simple List" to "Custom Expression." Set the _Data_ value of the expression to **genres** and the Display Text to **item**. Run the page in preview and see the example below.

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-6de8b85f1448631b2fe2fa35fbe47482ff6819f2%2Fcreating-a-dropdown-v1715-7.png?alt=media)

To add another genre to the list, simply go back to the Data Builder and add another row for the "Science Fiction" genre. Notice how the list will automatically contain the new item.

### Selecting multiple items from a list

The dropdown list that has been covered so far is for selecting single items from a list. In the case where multiple items can be selected, using a list of checkboxes might be more appropriate. In the example above, perhaps a book is a Youth Mystery book.

Replacing the dropdown list with a checkbox list will allow for this multiple selections of Genres. Go to the container containing the genre dropdown and remove the dropdown list. Add a Checkbox List from the Add control dialog, it is under the Repeater section. Add a checkbox and a label to the checkbox cell. Select the Checkbox List and set the data to **genres**. In order to store the selected genres, go to the Page and add a variable typed list of text named **selected\_genres**. On the Checkbox List set the value to **selected\_genres**. Set the text of the label to **item**.

Preview the app:

![organizing info](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-1a8740f9a565c4d8a62f8055581852a47f2afabc%2Fcreating-a-dropdown-v1715-8.png?alt=media)

### When Dropdown lists are desirable

#### How Dropdowns compare to other list controls

Dropdowns are just one of several list selection controls in Airkit. The other major possibilities include Checkboxes and Radio Lists. Dropdown lists allow the user to select one item from a list of items. Dropdown lists do this in a relatively small amount of screen real estate. The list expands when the user interacts and only shows the selection after. Radio lists have similar behavior of selecting one item from a list, but display all items visually, even once selected. Checkboxes on the other hand display all items visually but allow for multiple items to be selected.

#### Why should I use a dropdown?

Dropdowns help with screen space. Use a dropdown on a form where there are a bunch of options and the user must select one. Because the dropdown options are only visible when editing the control, if there are too many options a dropdown might not be the best solution. Scrolling through many items, especially on a mobile device, can be challenging for some users.

## Dropdown Menus with Complex Data

### Configuring a dropdown to select a Salesforce Contact

Salesforce contacts are complex objects. Using some Airscript, it is possible to populate a dropdown list to select a Salesforce contact. See [Additional Reference](https://github.com/airkit/airkit-docs/blob/master/docs/v17-15/complex-objects-in-a-dropdown.md#additional-reference) for more information on a mock salesforce contact.

This example assumes a connection to a Salesforce instance with an integration. To configure your Salesforce Instance, check out [Creating a Salesforce Lead](../integration-guides/create-a-salesforce-lead) for information on how to connect a Salesforce integration.

Go to [Connection Builder](../../studio/builder-bar/connection-builder) and create a new Data Flow. Name it "SF - Get Contacts". Change the data operation to type "Salesforce." Select the Salesforce Datasource, and select "Find Records" for the operation type. Choose Contact (Contact) for the _Object Type._ Add several fields, make sure Full Name is included. Run the operation and the step should return data in the format:

```javascript
{  
  "success": true,  
  "result": [  
  {  
    "Id": "0034x000007Ro68AAC",  
    "AccountId": "0014x000009psYGAAY",  
    "LastName": "Gonzalez",  
    "FirstName": "Rose",  
    "Name": "Rose Gonzalez",  
    "Salutation": "Ms.",  
    "MailingStreet": "313 Constitution Place\nAustin, TX 78767\nUSA",  
    ...
```

Because the list of contacts is in the **result** property of the Salesforce response, create another Data Operation of type Transform. Insert the following snippet into the transform box:

```javascript
Salesforce.result
```

This strips the extra return information from Salesforce and just returns the data in the form of a list of results. Return the **transform** from the Data Flow.

Go to Web Builder and create a new Web Flow. Name it "Corporate Buyers Program." Create a Web page and add a heading label with the text "Corporate Buyer's Club:" Add another label with the text "Select the account point person:" Create a dropdown list from the picker list of controls. Lastly add a submit button. The page should look something like this:

![Drop down](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-acd221e5031388101315ac05d28029326693083e%2Fcreating-a-dropdown-v1715-9.png?alt=media)

To connect this to the Data Flow, select the Web Page. In the inspector Add a variable **contacts** of List of Any type. Create a second variable called **selected\_contact** of type Any. With the page still selected, under the Actions tab add a [Run Data Flow](../../actions/the-run-data-flow-action) action to the "Card Updated" event. Set the action the "SF - Get Contacts" data flow and set **contacts** for the output variable. This will populate the variable at the time the card is first created.

Select the Dropdown List. In the Data Binding section, change the "Value" to a custom expression and enter **selected\_contact.** This will store the currently selected contact with all of the fields. Change "Type of List" to _Custom Expression._ For Data select contacts. This will use the list returned from the Data Flow. Set the display text to **item.Name**. This is the text that will display for each item in the dropdown list. For "Value Text", put in **item**. This will put the entire contact record into **selected\_contact**. For the "Selected" field, insert:

```javascript
selected_contact.Id = item.Id
```

This expression will evaluate to true if the item has the same **Id** as the selected contact's **Id**. This is more reliable than checking on Name because it is possible to two contacts to have the same name, but not the same Id. The configuration of the dropdown should look like this:

![Airbooks-CustomDrop-DropdownConfig.png](https://a01-support.airkit.com/complex-objects-in-a-dropdown/Airbooks-CustomDrop-DropdownConfig.png)

Save, configure the launch trigger and run in Preview. Interaction with your dropdown should be similar to the following:

![Airbooks-CustomDrop-DropdownConfig.gif](https://a01-support.airkit.com/complex-objects-in-a-dropdown/Airbooks-Dropdown-CustomObj.gif)

Note that even though the example is just selecting the contact's name, the actual value of **selected\_contact** is the full Salesforce contact. This means that **selected\_contact** will have all the additional properties selected from the original object.

### Working with complex objects and dynamic dropdowns

If a dropdown list becomes too large, it can be difficult for users to find the exact item they are looking for. It can be easier to group items into a category and allow the user to specify the item within that category.

To demonstrate this let's build a simple example of a towing app. This will ask the user for the Make of a car first then display the items within the make.

Go to [Data Builder](../../studio/builder-bar/data-builder) and add a new AirData App Object named "Car." Give it text properties of "Make", "Year", and "Model." Populate the AirData table with some data. Click save and click "Continue and Save" on the migration dialog.

Go to [Connection Builder](../../studio/builder-bar/connection-builder) and create a new Data Flow named "AD - Fetch cars." Select the AirData option from the Data Operation dropdown. Select Car from the "App Object" dropdown. Leave type query, select paginate and run the operation. Add a transform after to return only the results:

```javascript
objectService.results
```

Go to [Web Builder](../../studio/action-builder) and create a new Web Flow. Create a new web page and add a label and a dropdown. Set the label to text to "Select Your Vehicle:" Select the web page and add a variable for **all\_cars** with the type List of Car, add another variable **selected\_car** with type Car.

Select the Dropdown List. Change the value of the Data Binding Value to "Custom Expression" and enter **selected\_car**. Set the "Type of List" to _Custom Expression_. Fill in the values:

| Data         | Designation                                    |
| ------------ | ---------------------------------------------- |
| All Data     | **all\_cars**                                  |
| Display Text | `"{{item.make}} {{item.model}} {{item.year}}"` |
| Value Text   | **item**                                       |
| Selected     | `item.__id = selected_car.__id`                |

The **.\_\_id** property is how the AirData table uniquely identifies each row. It is possible to use it here as a unique identifier for each row rather than comparing the make, then model, then the year.

Preview the app. Notice how long the list is with all the options are:

![Airbooks-CustomDrop-DropdownConfig.png](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-8839f2d19e59948e3b6e60c0bb21c140e7cc82c2%2Fcreating-a-dropdown-v1715-10.png?alt=media)

Depending on the list of cars supported, the user could be scrolling for a very long time to find their car. This process can be improved by changing this one dropdown to three separate dropdowns, one for Make, one for Model, and the last for a year.

Create a new Web Flow. Create a new Web Page. Add a container with a label and a dropdown. Set the text of the label to "Select a make:." Select the Web page and add the following variables:

| Variable Name       | Variable Type |
| ------------------- | ------------- |
| **all\_cars**       | List of Car   |
| **selected\_make**  | Text          |
| **selected\_model** | Text          |
| **selected\_car**   | Car           |

Select the Dropdown and set the value to **selected\_make**. Change the "Type Of List" to _Custom Expression._ Set "Data" equal to:

```javascript
FROM  
  car  
IN  
  all_cars  
SELECT DISTINCT  
  car.make
```

This is using a Query Expression to pull out all the distinct makes from the list of **all\_cars**.

Repeating the step for Model. Create a container with another label and dropdown. Set the text of the label to "Select a Model:." Set the value of the dropdown list to an Expression with the **selected\_model** value. Change the list type to "Custom Expression"  and set the Data to:

```javascript
FROM  
  car  
IN  
  all_cars  
WHERE  
  car.make = selected_make  
SELECT DISTINCT  
  car.model
```

Change the "Selected" option to **selected\_model = item**. Because the model can only be used once the make has been selected. With the container selected to the Advanced tab in the inspector and set "Is Visible" to **ISNOTEMPTY(selected\_make)**. This will keep the user from selecting a model without having first selected a make.

Create one more container for the year. Add a dropdown and a label. Set the label text equal to "Select a Year:". Change the Dropdown's Data Binding value to **selected\_car**. Set the Data to:

```javascript
FROM  
  car  
IN  
  all_cars  
WHERE  
  car.make = selected_make  
  AND car.model = selected_model  
SELECT DISTINCT  
  car
```

Set the display text to **item.year**. Set the value text to **item**. Set the "Selected" to **selected\_car.\_\_id = item.\_\_id**. Because this is the final dropdown, the entire car is selected in the **selected\_car**, whereas in the previous examples, only the value was selected. This will allow access to all properties on the car in the rest of the page. The properties on the data section for the Dropdown should look like:

&#x20;&#x20;

![Airbooks-CustomDrop-DropdownConfig.png](https://a01-support.airkit.com/complex-objects-in-a-dropdown/AirTow-SelectedCarDropDown.png)

Because the value year is not able to be selected until both the make and model are selected, set the visibility on the container for the year to:

```javascript
ISNOTEMPTY(  
  selected_model  
)  
AND ISNOTEMPTY(  
  selected_make  
)
```

Now the flow should work as desired:

![Airbooks-CustomDrop-DropdownConfig.png](https://1191388742-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhOn9CLWoV9VfJeM5EDAa%2Fuploads%2Fgit-blob-8839f2d19e59948e3b6e60c0bb21c140e7cc82c2%2Fcreating-a-dropdown-v1715-10.png?alt=media)

### Additional Reference

**Mock Salesforce Contact**

Example of a mock Salesforce Contact Record:

```javascript
{  
  "attributes": {  
    "type": "Contact",  
    "url": "/services/data/v45.0/sobjects/Contact/0035Y00003p12fmQAA"  
  },  
  "Id": "0035Y00003p12fmQAA",  
  "IsDeleted": false,  
  "MasterRecordId": null,  
  "AccountId": "0015Y00002cnHiUQAU",  
  "LastName": "Gonzalez",  
  "FirstName": "Rose",  
  "Salutation": "Ms.",  
  "Name": "Rose Gonzalez",  
  "OtherStreet": null,  
  "OtherCity": null,  
  "OtherState": null,  
  "OtherPostalCode": null,  
  "OtherCountry": null,  
  "OtherLatitude": null,  
  "OtherLongitude": null,  
  "OtherGeocodeAccuracy": null,  
  "OtherAddress": null,  
  "MailingStreet": "313 Constitution Place\nAustin, TX 78767\nUSA",  
  "MailingCity": null,  
  "MailingState": null,  
  "MailingPostalCode": null,  
  "MailingCountry": null,  
  "MailingLatitude": null,  
  "MailingLongitude": null,  
  "MailingGeocodeAccuracy": null,  
  "MailingAddress": {  
    "city": null,  
    "country": null,  
    "geocodeAccuracy": null,  
    "latitude": null,  
    "longitude": null,  
    "postalCode": null,  
    "state": null,  
    "street": "313 Constitution Place\nAustin, TX 78767\nUSA"  
  },  
  "Phone": "(512) 757-6000",  
  "Fax": "(512) 757-9000",  
  "MobilePhone": "(512) 757-9340",  
  "HomePhone": null,  
  "OtherPhone": null,  
  "AssistantPhone": null,  
  "ReportsToId": null,  
  "Email": "rose@edge.com",  
  "Title": "SVP, Procurement",  
  "Department": "Procurement",  
  "AssistantName": null,  
  "LeadSource": "Trade Show",  
  "Birthdate": "1969-02-19",  
  "Description": null,  
  "OwnerId": "0055Y00000F9t8fQAB",  
  "CreatedDate": "2021-03-09T17:17:51.000+0000",  
  "CreatedById": "0055Y00000F9t8fQAB",  
  "LastModifiedDate": "2021-03-09T17:17:51.000+0000",  
  "LastModifiedById": "0055Y00000F9t8fQAB",  
  "SystemModstamp": "2021-03-09T17:17:51.000+0000",  
  "LastActivityDate": null,  
  "LastCURequestDate": null,  
  "LastCUUpdateDate": null,  
  "LastViewedDate": null,  
  "LastReferencedDate": null,  
  "EmailBouncedReason": null,  
  "EmailBouncedDate": null,  
  "IsEmailBounced": false,  
  "PhotoUrl": "/services/images/photo/0035Y00003p12fmQAA",  
  "Jigsaw": null,  
  "JigsawContactId": null,  
  "CleanStatus": "Pending",  
  "IndividualId": null,  
  "Level__c": "Primary",  
  "Languages__c": "English"  
}
```
