# Show / Hide UI Components

JourneyApps supports dynamically showing and hiding UI components in mobile apps. This is useful for use cases like:

* Conditionally showing input fields based on a user's previous inputs (for example, "If you are married, fill in your spouse's details")
* Showing different menu buttons on the main screen of the app depending on the user's "role" (for example, only managers see an *Administration* section)
* ... etc.

### How to Show/Hide Components

In short, most view components (see *Supported Components* below for full details) support a `show-if` or `hide-if` option in the View XML that controls whether the component is hidden or shown. `show-if` or `hide-if` can either be a literal boolean value (`true` or `false`), or it can specify a variable, parameter or field that can be a string, number, object, etc. that **evaluates to false** or **evaluates to true** (see below for full details).

If a component has a `required="true"` validation specified, but it is hidden, the validation will be ignored/skipped.

If you use a variable or field for `show-if` or `hide-if` to control visibility, you can dynamically change the value of that variable/field in order to dynamically toggle the visibility of a component (examples are provided below).

### Supported Components

Any component can have a `show-if` or `hide-if` option, with the following exceptions:

* [`sidebar`](https://docs.journeyapps.com/reference/build/ui-components/all-ui-components/sidebar) itself can't be hidden, but individual sidebar items may be hidden
* [`capture-coordinates`](https://docs.journeyapps.com/reference/build/ui-components/all-ui-components/capture-coordinates) - will still capture a location in the background

### Valid Arguments to Determine Showing/Hiding

`show-if` or `hide-if` can either be a literal boolean value (`true` or `false`), or it can specify a variable, parameter or field that can be a string, number, object, etc. that **evaluates to false** or **evaluates to true**

The default JavaScript behavior is used to determine whether something **evaluates to false** or **evaluates to true**:

| Type                                             | Behavior                                                   |
| ------------------------------------------------ | ---------------------------------------------------------- |
| `integer`, `number`, and `single-choice-integer` | `0` and `null` are false, everything else is true          |
| `text`                                           | empty string and `null` are false, everything else is true |
| `single-choice`                                  | `null` (no selection) is false, everything else is true    |
| `objects`                                        | `null` is false, an object is true                         |
| `location`                                       | `null` is false, object is true                            |
| `multiple-choice` and `multiple-choice-integer`  | `null` and empty selection is false, any selection is true |
| `boolean`                                        | `null` and `false` are false, `true` is true               |

### Examples

#### Example - Hide/Show Inputs Based on Prior Input

In this example, we have a dropdown list to select a Province, and a dropdown list to select a City within the selected Province. The dropdown list for the City only shows once the user selected a Province. We also show a *"You selected:"* status message when the user selected a city.

{% code title="main.view\.xml" %}

```xml
<var name="provinces" type="query:province" />
<var name="selected_province" type="province" />
<var name="selected_city" type="city" />

<object-list bind="selected_province" query="provinces" label="Province" required="true" />

<object-dropdown how-if="selected_province" bind="selected_city" query="selected_province.cities" label="City" required="true" />

<info show-if="city" label="You selected" >{selected_city}</info>
```

{% endcode %}

#### Example - Show or Hide Based on User Role

In this example, a single mobile app will be used by both Salespeople and Technicians at a company. However, Technicians should only have access to Job Card related functionality, whereas Salespeople should only have access to Sales Quote related functionality. We accomplish this by having two menu buttons on a view that show or hide depending on what the user's role is (we use an `single-choice` to store each user's role)

{% code title="main.view\.xml" %}

```xml
<var name="is_technician" type="boolean" />
<var name="is_salesperson" type="boolean" />

<button-group>
    <button show-if="is_technician" label="Job Cards" icon="icons/job_cards.png"  />
    <button show-if="is_salesperson" label="Sales Quotes" icon="icons/sales_quotes.png" />
</button-group>
```

{% endcode %}

{% code title="main.js" %}

```javascript
function init() {
    // 'role' is a single-choice on the 'user' object where 'technician' = Technician and 'salesperson' = Salesperson
    if (user.role == 'technician') {
        view.is_technician = true;
        view.is_salesperson = false;
    } else if (user.role == 'salesperson') {
        view.is_technician = false;
        view.is_salesperson = true;
    }
}
```

{% endcode %}

#### Example - Trigger Show/Hide From JavaScript

This example shows how we can dynamically control the showing/hiding of components from JavaScript/TypeScript. If the user presses a button, we hide or show the heading above the button.

{% code title="main.js" %}

```javascript
function init() {
    // initially the heading will be visible
    view.hide_me = false;
}

function hideMeShowMe() {
    if (view.hide_me == false) { // if the heading is visible,
        view.hide_me = true; // hide the heading
    } else {
        view.hide_me = false; // show the heading
    }
}
```

{% endcode %}

{% code title="main.view\.xml" %}

```xml
<var name="hide_me" type="boolean" />

<heading hide-if="hide_me">I will be hidden when the user presses the below button!</heading>
<button label="Hide/Show Heading" on-press="$:hideMeShowMe()" />
```

{% endcode %}

#### Example - Background GPS Capturing

{% hint style="warning" %}
**Note:** The visibility of a GPS component cannot be dynamically controlled. It must be either visible or specifically hidden (see below).
{% endhint %}

Normally, a `capture-coordinates` component in JourneyApps will show a map to the user indicating what GPS location is being captured. However, often you want to capture a GPS location in the background without displaying a map to the user. Hiding the component will cause it to continue capturing a GPS location in the background.hint

```xml
<capture-coordinates show-if="false" label="User Location" bind="user.location" />
```
