Edit this page

API Switching form state

A field with the [up-switch] attribute can control the state of other element when the field changes.

Common effects are showing, hiding or disabling another element. You can also implement custom switching effects.

Tip

The [up-switch] attribute handles light, client-side effects. See Reactive server forms for effects that render on the server.

Showing or hiding other elements

The controlling form field gets an [up-switch] attribute with a selector for the elements to show or hide:

<select name="level" up-switch=".level-dependent">
  <option value="beginner">beginner</option>
  <option value="intermediate">intermediate</option>
  <option value="expert">expert</option>
</select>

The target elements can use [up-show-for] and [up-hide-for] attributes to indicate for which values they should be shown or hidden:

<div class="level-dependent" up-show-for="beginner"> <!-- mark: up-show-for="beginner" -->
  shown for beginner level, hidden for other levels
</div>

<div class="level-dependent" up-hide-for="beginner"> <!-- mark: up-hide-for="beginner" -->
  hidden for beginner level, shown for other levels
</div>

By default the entire form will be searched for matches. This can be configured.

To toggle an element for multiple values, separate with a space or comma:

<div class="level-dependent" up-show-for="intermediate expert"> <!-- mark: up-show-for="intermediate expert" -->
  only shown for intermediate and expert levels
</div>

Disabling or enabling fields

The controlling field gets an [up-switch] attribute with a selector for the fields to disable for enable:

<select name="role" up-switch=".role-dependent">
  <option value="trainee">Trainee</option>
  <option value="manager">Manager</option>
</select>

The target elements can use [up-enable-for] and [up-disable-for] attributes to indicate for which values they should be shown or hidden:

<!-- The department field is only shown for managers -->
<input class="role-dependent" name="department" up-enable-for="manager"> <!-- mark: up-enable-for="manager" -->

<!-- The mentor field is only shown for trainees -->
<input class="role-dependent" name="mentor" up-disable-for="manager"> <!-- mark: up-disable-for="manager" -->

Custom switching effects

[up-switch] allows you to implement your own switching effects. For example, we want a custom [highlight-for] attribute. It draws a bright outline around the department field when the manager role is selected:

<select name="role" up-switch=".role-dependent">
  <option value="trainee">Trainee</option>
  <option value="manager">Manager</option>
</select>

<input class="role-dependent" name="department" highlight-for="manager"> <!-- mark: highlight-for="manager" -->

When the role select changes, an up:form:switch event is emitted on all elements matching .role-dependent. We can use this event to implement our custom [highlight-for] effect:

up.on('up:form:switch', '[highlight-for]', (event) => {
  let highlightedValue = event.target.getAttribute('highlight-for')
  let isHighlighted = (event.field.value === highlightedValue)
  event.target.style.highlight = isHighlighted ? '2px solid orange' : ''
})

Tip

To implement asynchronous effects that are rendered on the server, see Reactive server forms.

Switching for multiple values

To switch for multiple values, separate them with a space or comma:

<div class="level-dependent" up-show-for="intermediate expert"> <!-- mark: up-show-for="intermediate expert" -->
  only shown for intermediate and expert levels
</div>

If your values might contain spaces, you may also serialize them as a relaxed JSON array:

<div class='level-dependent' up-show-for='["John Doe", "Jane Doe"]'> <!-- mark: up-show-for='["John Doe", "Jane Doe"]' -->
  You selected John or Jane Doe
</div>

Switching on blank or present values

Instead of switching on specific string values, you can use :blank to match an empty input value:

<input type="text" name="user" up-switch=".target">

<div class="target" up-show-for=":blank"> <!-- mark: up-show-for=":blank" -->
  please enter a username
</div>

Inversely, :present will match any non-empty input value:

<div class="target" up-hide-for=":present"> <!-- mark: up-hide-for=":present" -->
  please enter a username
</div>

Usage with checkboxes

For checkboxes you may match against the pseudo-values :checked or :unchecked:

<input type="checkbox" name="flag" up-switch=".flag-dependent">

<div class="flag-dependent" up-show-for=":checked">
  only shown when checkbox is checked
</div>

<div class="flag-dependent" up-show-for=":unchecked">
  only shown when checkbox is unchecked
</div>

You may also match against the [value] attribute of the checkbox element:

<input type="checkbox" name="flag" value="active" up-switch=".flag-dependent">

<div class="flag-dependent" up-show-for="active">
  only shown when checkbox is checked
</div>

Array fields

When you have multiple checkboxes for a single array field, set [up-switch] on an element containing all checkboxes:

<div up-switch=".department-dependent">
  <input type="checkbox" name="department[]" value="development"> Development
  <input type="checkbox" name="department[]" value="sales"> Sales
  <input type="checkbox" name="department[]" value="accounting"> Accounting
</div>

<div class="department-dependent" up-show-for="sales, accounting">
  shown when either sales or accounting is checked
</div>

Usage with radio buttons

Use [up-switch] on a container for a radio button group:

<div up-switch=".level-dependent"> <!-- mark: <div> -->
  <input type="radio" name="level" value="beginner">
  <input type="radio" name="level" value="intermediate">
  <input type="radio" name="level" value="expert">
</div> <!-- mark: </div> -->

<div class="level-dependent" up-show-for="beginner">
  shown for beginner level, hidden for other levels
</div>

<div class="level-dependent" up-hide-for="beginner">
  hidden for beginner level, shown for other levels
</div>

Changing the switched region

By default the entire form will be searched for matches. You can narrow or expand the search scope by setting an [up-switch-region] attribute on the controlling field.

To match all elements within the current layer, set the region to :layer:

<form method="post" action="/order">
  <select name="payment" up-switch="#info" up-switch-region=":layer"> <!-- mark: up-switch-region=":layer" -->
    <option value="paypal">PayPal</option>
    <option value="manual">Manual wire transfer</option>
  </select>
</form>

<div id="info" up-show-for="paypal">
  You will be redirected to PayPal to complete your order.
</div>

<div id="info" up-show-for="manual">
  We will ship your package once we receive your transfer.
</div>

Reacting to different events

By default switch effects are applied for every input event. For example, text fields will switch other elements as the user is typing:

<input type="text" name="user" up-switch=".user-dependent">

<div class="user-dependent" up-show-for="alice">
  only shown for user alice
</div>

You can watch for other events by setting an [up-watch-event] attribute. For example, listening to change will wait until the text field is blurred before applying any switching effects:

<input type="text" name="user" up-switch=".user-dependent" up-watch-event="change"> <!-- mark: up-watch-event="change" -->

When watching a fast-firing event like input, you can debounce the switching effect with an [up-watch-delay] attribute:

<input type="text" name="user" up-switch=".user-dependent" up-watch-event="input" up-watch-delay="150"> <!-- mark: up-watch-delay="150" -->