Data input
Conditional Field
A field that shows while another field of its form has a given value, written as one attribute.
| Class name | Type | Description |
|---|---|---|
fieldplf:field | Component | A label, a control and its messages |
field-labelplf:field-label | Part | The control's label |
field-legendplf:field-legend | Part | The fieldset's legend |
field-groupplf:field-group | Modifier | A fieldset of fields, without its border |
Default
Place the field after the one it depends on, so it appears where the reader goes next.
<form class="flex flex-col gap-4">
<div class="field">
<label class="field-label" for="conditional-mailer">Mailer</label>
<select class="select" id="conditional-mailer" name="mailer">
<option value="php">PHP mail</option>
<option value="smtp">SMTP</option>
</select>
</div>
<fieldset class="field field-group" data-plf-show-if="mailer=smtp">
<legend class="field-legend">SMTP server</legend>
<div class="field">
<label class="field-label" for="conditional-host">Host</label>
<input class="input" id="conditional-host" name="smtp-host" required>
</div>
<div class="field">
<label class="field-label" for="conditional-port">Port</label>
<input class="input" id="conditional-port" name="smtp-port" type="number" value="587">
</div>
</fieldset>
</form><form class="plf:flex plf:flex-col plf:gap-4">
<div class="plf:field">
<label class="plf:field-label" for="conditional-mailer">Mailer</label>
<select class="plf:select" id="conditional-mailer" name="mailer">
<option value="php">PHP mail</option>
<option value="smtp">SMTP</option>
</select>
</div>
<fieldset class="plf:field plf:field-group" data-plf-show-if="mailer=smtp">
<legend class="plf:field-legend">SMTP server</legend>
<div class="plf:field">
<label class="plf:field-label" for="conditional-host">Host</label>
<input class="plf:input" id="conditional-host" name="smtp-host" required>
</div>
<div class="plf:field">
<label class="plf:field-label" for="conditional-port">Port</label>
<input class="plf:input" id="conditional-port" name="smtp-port" type="number" value="587">
</div>
</fieldset>
</form>'use client';
import { useState } from 'react';
import { Field, FieldGroup, Input, Select } from '@pelatform/react';
export function Example() {
const [mailer, setMailer] = useState('php');
return (
<form className="flex flex-col gap-4">
<Field label="Mailer">
<Select name="mailer" value={mailer} onChange={event => setMailer(event.target.value)}>
<option value="php">PHP mail</option>
<option value="smtp">SMTP</option>
</Select>
</Field>
{mailer === 'smtp' && (
<FieldGroup legend="SMTP server">
<Field label="Host">
<Input name="smtp-host" required />
</Field>
<Field label="Port">
<Input name="smtp-port" type="number" defaultValue={587} />
</Field>
</FieldGroup>
)}
</form>
);
}'use client';
import { useState } from 'react';
import { Field, FieldGroup, Input, Select } from '@pelatform/react/prefixed';
export function Example() {
const [mailer, setMailer] = useState('php');
return (
<form className="plf:flex plf:flex-col plf:gap-4">
<Field label="Mailer">
<Select name="mailer" value={mailer} onChange={event => setMailer(event.target.value)}>
<option value="php">PHP mail</option>
<option value="smtp">SMTP</option>
</Select>
</Field>
{mailer === 'smtp' && (
<FieldGroup legend="SMTP server">
<Field label="Host">
<Input name="smtp-host" required />
</Field>
<Field label="Port">
<Input name="smtp-port" type="number" defaultValue={587} />
</Field>
</FieldGroup>
)}
</form>
);
}<form class="flex flex-col gap-4">
<div class="choice">
<input class="checkbox" id="conditional-copy" name="send-copy" type="checkbox">
<label class="choice-label" for="conditional-copy">Send me a copy</label>
</div>
<div class="field" data-plf-show-if="send-copy">
<label class="field-label" for="conditional-copy-email">Copy to</label>
<input class="input" id="conditional-copy-email" name="copy-email" type="email" dir="ltr" autocomplete="email">
</div>
<div class="choice">
<input class="checkbox" id="conditional-same" name="same-address" type="checkbox" checked>
<label class="choice-label" for="conditional-same">Ship to my billing address</label>
</div>
<div class="field" data-plf-show-if="!same-address">
<label class="field-label" for="conditional-shipping">Shipping address</label>
<textarea class="textarea" id="conditional-shipping" name="shipping-address" rows="3"></textarea>
</div>
</form><form class="plf:flex plf:flex-col plf:gap-4">
<div class="plf:choice">
<input class="plf:checkbox" id="conditional-copy" name="send-copy" type="checkbox">
<label class="plf:choice-label" for="conditional-copy">Send me a copy</label>
</div>
<div class="plf:field" data-plf-show-if="send-copy">
<label class="plf:field-label" for="conditional-copy-email">Copy to</label>
<input class="plf:input" id="conditional-copy-email" name="copy-email" type="email" dir="ltr" autocomplete="email">
</div>
<div class="plf:choice">
<input class="plf:checkbox" id="conditional-same" name="same-address" type="checkbox" checked>
<label class="plf:choice-label" for="conditional-same">Ship to my billing address</label>
</div>
<div class="plf:field" data-plf-show-if="!same-address">
<label class="plf:field-label" for="conditional-shipping">Shipping address</label>
<textarea class="plf:textarea" id="conditional-shipping" name="shipping-address" rows="3"></textarea>
</div>
</form>'use client';
import { useState } from 'react';
import { Checkbox, Field, Input, Textarea } from '@pelatform/react';
export function Example() {
const [sendCopy, setSendCopy] = useState(false);
const [sameAddress, setSameAddress] = useState(true);
return (
<form className="flex flex-col gap-4">
<Checkbox name="send-copy" checked={sendCopy} onChange={event => setSendCopy(event.target.checked)}>Send me a copy</Checkbox>
{sendCopy && (
<Field label="Copy to">
<Input name="copy-email" type="email" dir="ltr" autoComplete="email" />
</Field>
)}
<Checkbox name="same-address" checked={sameAddress} onChange={event => setSameAddress(event.target.checked)}>Ship to my billing address</Checkbox>
{!sameAddress && (
<Field label="Shipping address">
<Textarea name="shipping-address" rows={3} />
</Field>
)}
</form>
);
}'use client';
import { useState } from 'react';
import { Checkbox, Field, Input, Textarea } from '@pelatform/react/prefixed';
export function Example() {
const [sendCopy, setSendCopy] = useState(false);
const [sameAddress, setSameAddress] = useState(true);
return (
<form className="plf:flex plf:flex-col plf:gap-4">
<Checkbox name="send-copy" checked={sendCopy} onChange={event => setSendCopy(event.target.checked)}>Send me a copy</Checkbox>
{sendCopy && (
<Field label="Copy to">
<Input name="copy-email" type="email" dir="ltr" autoComplete="email" />
</Field>
)}
<Checkbox name="same-address" checked={sameAddress} onChange={event => setSameAddress(event.target.checked)}>Ship to my billing address</Checkbox>
{!sameAddress && (
<Field label="Shipping address">
<Textarea name="shipping-address" rows={3} />
</Field>
)}
</form>
);
}<form class="flex flex-col gap-4">
<fieldset class="field field-group">
<legend class="field-legend">Plan</legend>
<div class="choice">
<input class="radio" id="conditional-solo" name="plan" value="solo" type="radio" checked>
<label class="choice-label" for="conditional-solo">Solo</label>
</div>
<div class="choice">
<input class="radio" id="conditional-team" name="plan" value="team" type="radio">
<label class="choice-label" for="conditional-team">Team</label>
</div>
<div class="choice">
<input class="radio" id="conditional-enterprise" name="plan" value="enterprise" type="radio">
<label class="choice-label" for="conditional-enterprise">Enterprise</label>
</div>
</fieldset>
<div class="field" data-plf-show-if="plan=team,enterprise">
<label class="field-label" for="conditional-workspace">Workspace name</label>
<input class="input" id="conditional-workspace" name="workspace" required>
</div>
</form><form class="plf:flex plf:flex-col plf:gap-4">
<fieldset class="plf:field plf:field-group">
<legend class="plf:field-legend">Plan</legend>
<div class="plf:choice">
<input class="plf:radio" id="conditional-solo" name="plan" value="solo" type="radio" checked>
<label class="plf:choice-label" for="conditional-solo">Solo</label>
</div>
<div class="plf:choice">
<input class="plf:radio" id="conditional-team" name="plan" value="team" type="radio">
<label class="plf:choice-label" for="conditional-team">Team</label>
</div>
<div class="plf:choice">
<input class="plf:radio" id="conditional-enterprise" name="plan" value="enterprise" type="radio">
<label class="plf:choice-label" for="conditional-enterprise">Enterprise</label>
</div>
</fieldset>
<div class="plf:field" data-plf-show-if="plan=team,enterprise">
<label class="plf:field-label" for="conditional-workspace">Workspace name</label>
<input class="plf:input" id="conditional-workspace" name="workspace" required>
</div>
</form>'use client';
import { useState } from 'react';
import { Field, FieldGroup, Input, Radio } from '@pelatform/react';
export function Example() {
const [plan, setPlan] = useState('solo');
return (
<form className="flex flex-col gap-4">
<FieldGroup legend="Plan">
<Radio name="plan" value="solo" checked={plan === 'solo'} onChange={event => setPlan(event.target.value)}>Solo</Radio>
<Radio name="plan" value="team" checked={plan === 'team'} onChange={event => setPlan(event.target.value)}>Team</Radio>
<Radio name="plan" value="enterprise" checked={plan === 'enterprise'} onChange={event => setPlan(event.target.value)}>Enterprise</Radio>
</FieldGroup>
{(plan === 'team' || plan === 'enterprise') && (
<Field label="Workspace name">
<Input name="workspace" required />
</Field>
)}
</form>
);
}'use client';
import { useState } from 'react';
import { Field, FieldGroup, Input, Radio } from '@pelatform/react/prefixed';
export function Example() {
const [plan, setPlan] = useState('solo');
return (
<form className="plf:flex plf:flex-col plf:gap-4">
<FieldGroup legend="Plan">
<Radio name="plan" value="solo" checked={plan === 'solo'} onChange={event => setPlan(event.target.value)}>Solo</Radio>
<Radio name="plan" value="team" checked={plan === 'team'} onChange={event => setPlan(event.target.value)}>Team</Radio>
<Radio name="plan" value="enterprise" checked={plan === 'enterprise'} onChange={event => setPlan(event.target.value)}>Enterprise</Radio>
</FieldGroup>
{(plan === 'team' || plan === 'enterprise') && (
<Field label="Workspace name">
<Input name="workspace" required />
</Field>
)}
</form>
);
}Nested
A field inside a hidden one hides with it, and a disabled field has no value, so one condition can follow another.
<form class="flex flex-col gap-4">
<div class="field">
<label class="field-label" for="conditional-notify">Notifications</label>
<select class="select" id="conditional-notify" name="notify">
<option value="off">Off</option>
<option value="email">Email</option>
<option value="webhook">Webhook</option>
</select>
</div>
<fieldset class="field field-group" data-plf-show-if="notify=webhook">
<legend class="field-legend">Webhook</legend>
<div class="field">
<label class="field-label" for="conditional-webhook">URL</label>
<input class="input" id="conditional-webhook" name="webhook-url" type="url" dir="ltr" required>
</div>
<div class="choice">
<input class="checkbox" id="conditional-sign" name="sign" type="checkbox">
<label class="choice-label" for="conditional-sign">Sign requests</label>
</div>
<div class="field" data-plf-show-if="sign">
<label class="field-label" for="conditional-secret">Signing secret</label>
<input class="input" id="conditional-secret" name="signing-secret" type="password" autocomplete="off">
</div>
</fieldset>
</form><form class="plf:flex plf:flex-col plf:gap-4">
<div class="plf:field">
<label class="plf:field-label" for="conditional-notify">Notifications</label>
<select class="plf:select" id="conditional-notify" name="notify">
<option value="off">Off</option>
<option value="email">Email</option>
<option value="webhook">Webhook</option>
</select>
</div>
<fieldset class="plf:field plf:field-group" data-plf-show-if="notify=webhook">
<legend class="plf:field-legend">Webhook</legend>
<div class="plf:field">
<label class="plf:field-label" for="conditional-webhook">URL</label>
<input class="plf:input" id="conditional-webhook" name="webhook-url" type="url" dir="ltr" required>
</div>
<div class="plf:choice">
<input class="plf:checkbox" id="conditional-sign" name="sign" type="checkbox">
<label class="plf:choice-label" for="conditional-sign">Sign requests</label>
</div>
<div class="plf:field" data-plf-show-if="sign">
<label class="plf:field-label" for="conditional-secret">Signing secret</label>
<input class="plf:input" id="conditional-secret" name="signing-secret" type="password" autocomplete="off">
</div>
</fieldset>
</form>'use client';
import { useState } from 'react';
import { Checkbox, Field, FieldGroup, Input, Select } from '@pelatform/react';
export function Example() {
const [notify, setNotify] = useState('off');
const [sign, setSign] = useState(false);
return (
<form className="flex flex-col gap-4">
<Field label="Notifications">
<Select name="notify" value={notify} onChange={event => setNotify(event.target.value)}>
<option value="off">Off</option>
<option value="email">Email</option>
<option value="webhook">Webhook</option>
</Select>
</Field>
{notify === 'webhook' && (
<FieldGroup legend="Webhook">
<Field label="URL">
<Input name="webhook-url" type="url" dir="ltr" required />
</Field>
<Checkbox name="sign" checked={sign} onChange={event => setSign(event.target.checked)}>Sign requests</Checkbox>
{sign && (
<Field label="Signing secret">
<Input name="signing-secret" type="password" autoComplete="off" />
</Field>
)}
</FieldGroup>
)}
</form>
);
}'use client';
import { useState } from 'react';
import { Checkbox, Field, FieldGroup, Input, Select } from '@pelatform/react/prefixed';
export function Example() {
const [notify, setNotify] = useState('off');
const [sign, setSign] = useState(false);
return (
<form className="plf:flex plf:flex-col plf:gap-4">
<Field label="Notifications">
<Select name="notify" value={notify} onChange={event => setNotify(event.target.value)}>
<option value="off">Off</option>
<option value="email">Email</option>
<option value="webhook">Webhook</option>
</Select>
</Field>
{notify === 'webhook' && (
<FieldGroup legend="Webhook">
<Field label="URL">
<Input name="webhook-url" type="url" dir="ltr" required />
</Field>
<Checkbox name="sign" checked={sign} onChange={event => setSign(event.target.checked)}>Sign requests</Checkbox>
{sign && (
<Field label="Signing secret">
<Input name="signing-secret" type="password" autoComplete="off" />
</Field>
)}
</FieldGroup>
)}
</form>
);
}JavaScript
Conditional fields need JavaScript; without it every field shows and submits. The Full script (pelatform-ui.min.js) starts every component on page load, with no code of your own; with ESM imports, call init() yourself, as in Installation. For markup you add later, see Dynamic content.
<link rel="stylesheet" href="pelatform-ui.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.min.css">
<link rel="stylesheet" href="components/form.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/field.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script><link rel="stylesheet" href="pelatform-ui.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.prefixed.min.css">
<link rel="stylesheet" href="components/form.prefixed.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/field.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script>| Attribute | Purpose |
|---|---|
data-plf-show-if |
On any element, usually a field or a fieldset: shows it while its condition is true. Otherwise the script adds hidden and disables every enabled control inside it, so they neither submit nor block the form as required; it enables them again when the element shows, and their values stay |
The condition names another field of the same form, or of the root outside a form, by its name:
| Condition | Shows while the field … |
|---|---|
name=value |
Has this value |
name=a,b |
Has one of these values |
name!=value, name!=a,b |
Has none of them, or no value |
name |
Has a value: checked, chosen or filled in |
!name |
Has no value |
A value is what the form would submit, so a disabled field has none; a value cannot contain a comma.
Methods
| Method | Behavior |
|---|---|
PLF. |
Returns the element’s instance, creating it for valid markup |
PLF. |
Returns the instance or null |
instance. |
Checks the condition now, for example after your code sets a value without sending an event |
instance. |
Removes the listeners, shows the element and enables the controls the script disabled |
With ESM, import Field from @pelatform/ui/components/field.
Events
| Event | When |
|---|---|
plf: |
After the element shows and its controls are enabled |
plf: |
After the element hides and its controls are disabled |
Each event’s detail:
| Property | Value |
|---|---|
instance |
The Field instance |
reason |
trigger, or api from update |
trigger |
The control whose change decided it, or null from update |
Both bubble from the element. Initialization, a form reset and destroy() send no events.
React
@pelatform/react has no Conditional Field component: keep the value a condition reads in state, as each example’s React tab does, and render the field only while the condition holds. A field that is not rendered submits nothing, as a hidden one the script disables does, but it also starts empty when it shows again; keep its value in state too where it should come back, as the script keeps a hidden field’s.