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.
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 -->
shown for beginner level, hidden for other levels
</div>
<div class="level-dependent" up-hide-for="beginner"> <!-- mark: up-hide-for -->
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 comma:
<div class="level-dependent" up-show-for="intermediate, expert"> <!-- mark: up-show-for -->
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 -->
<!-- The mentor field is only shown for trainees -->
<input class="role-dependent" name="mentor" up-disable-for="manager"> <!-- mark: up-disable-for -->
[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 -->
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 comma:
<div class="level-dependent" up-show-for="intermediate, expert"> <!-- mark: 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: ["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"> <!-- mark: :blank -->
<div class="target" 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: :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 -->
<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 -->
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 -->