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.
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>
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" -->
[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.
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>
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>
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>
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>
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>
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>
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" -->