Skip to content

data-custom-validity

Set a form field’s validity message from an expression. An empty string means valid; anything else blocks submission and becomes the message the browser shows.

data-custom-validity="$a === $b ? '' : 'Values must match.'"
part
key forbidden
value required: the message, or '' when valid
minimum length
<form data-signals="{ user: '' }" data-on:submit="alert('submitted ' + $user)">
<div class="row"><input data-bind:user placeholder="username" data-custom-validity="$user.length >= 3 ? '' : 'At least three characters.'"> <button>Submit</button></div>
</form>

The message can read any signal, so “passwords must match” is one expression on the second field.

fields that depend on each other

The repeat field is invalid until it matches; try submitting.

<form data-signals="{ pw: '', pw2: '' }" data-on:submit="alert('ok')">
<div class="row"><input type="password" data-bind:pw placeholder="password"> <input type="password" data-bind:pw2 placeholder="repeat" data-custom-validity="$pw2 === $pw ? '' : 'Passwords must match.'"> <button>Save</button></div>
<p class="muted">The repeat field is invalid until it matches; try submitting.</p>
</form>

The validity state is the browser’s own, so CSS pseudo-classes and checkValidity() see it.

:invalid styling
<style>.live input:invalid { outline: 2px solid #c0392b } .live input:valid { outline: 2px solid #2e8b57 }</style>
<div data-signals="{ code: '' }">
<input data-bind:code placeholder="six digits" data-custom-validity="/^\d{6}$/.test($code) ? '' : 'Six digits, please.'">
</div>

Only elements with setCustomValidity (inputs, selects, textareas, buttons, output, fieldset, custom form-associated elements) accept the directive; others are reported as an error. Pair it with @post(url, { contentType: 'form' }), which refuses to send an invalid form and calls reportValidity() instead.

import { customValidity } from 'sigmx/plugins'

Registering customValidity adds 166 bytes brotli (191 gzip, 397 minified) on top of the core. See bundle sizes.