Form & validation
Form + Field provide layout, labels, help text and i18n validation using the shared rules from @thl-ui/core. Errors appear after the first submit and update live; messages follow the active locale.
Validation
Validation
vue
<ThlForm :values="v" @submit="submit">
<ThlField label="Name" name="name" :value="v.name" :rules="[rules.required(), rules.minLength(3)]" required v-slot="{ id }"><ThlInput :id="id" v-model="v.name" /></ThlField>
<ThlField label="Email" name="email" :value="v.email" :rules="[rules.required(), rules.email()]" required v-slot="{ id }"><ThlInput :id="id" v-model="v.email" type="email" /></ThlField>
<ThlField label="Password" name="password" :value="v.password" :rules="[rules.required(), rules.minLength(6)]" required v-slot="{ id }"><ThlInput :id="id" v-model="v.password" type="password" /></ThlField>
<ThlField label="Confirm" name="confirm" :value="v.confirm" :rules="[rules.match('password')]" v-slot="{ id }"><ThlInput :id="id" v-model="v.confirm" type="password" /></ThlField>
<ThlField name="agree" :value="v.agree" :rules="[rules.required()]"><ThlCheckbox v-model="v.agree" label="I agree to the terms" /></ThlField>
<ThlFormActions><ThlButton type="submit" variant="success" icon="check">Submit</ThlButton><ThlButton type="reset">Reset</ThlButton></ThlFormActions>
</ThlForm>tsx
import { Form, Field, FormActions, Input, Checkbox, Button, rules } from '@thl-ui/react';
<Form values={v} onSubmit={(values, ok) => ok && save(values)}>
<Field label="Email" name="email" value={v.email} rules={[rules.required(), rules.email()]} required>
{(id) => <Input id={id} type="email" value={v.email} onChange={(e) => setV({ ...v, email: e.target.value })} />}
</Field>
<Field name="agree" value={v.agree} rules={[rules.required()]}>
<Checkbox checked={v.agree} onChange={(agree) => setV({ ...v, agree })} label="I agree" />
</Field>
<FormActions><Button type="submit" variant="success">Submit</Button></FormActions>
</Form>html
form = new FormGroup({
email: new FormControl('', thlValidators(rules.required(), rules.email())),
agree: new FormControl(false, thlValidators(rules.required())),
});
<form class="thl-form" [formGroup]="form" (ngSubmit)="submit()">
<thl-field label="Email" for="email" required [control]="form.controls.email">
<input thlInput id="email" formControlName="email" />
</thl-field>
<thl-field [control]="form.controls.agree"><thl-checkbox formControlName="agree" label="I agree" /></thl-field>
<div class="thl-form__actions"><button thl-button type="submit" variant="success">Submit</button></div>
</form>Layouts & states
Layouts & states
vue
<div class="thl-row">
<div class="thl-col-12 thl-col-md-6"><ThlForm layout="horizontal"><ThlField label="Name" for="h1"><ThlInput id="h1" /></ThlField><ThlField label="Email" for="h2"><ThlInput id="h2" /></ThlField></ThlForm></div>
<div class="thl-col-12 thl-col-md-6"><ThlField label="Success" status="success" help="Looks good!"><ThlInput model-value="ok" /></ThlField><ThlField label="Error" error="Something went wrong"><ThlInput /></ThlField></div>
</div>tsx
<Form layout="horizontal">…</Form>
<Field label="Success" status="success" help="Looks good!"><Input defaultValue="ok" /></Field>
<Field label="Error" error="Something went wrong"><Input /></Field>html
<form class="thl-form thl-form--horizontal">…</form>
<thl-field label="Success" status="success" help="Looks good!"><input thlInput value="ok" /></thl-field>
<thl-field label="Error" error="Something went wrong"><input thlInput /></thl-field>Rules
rules.required(), email(), minLength(n), maxLength(n), min(n), max(n), number(), pattern(re), match(field). A rule is (value, allValues) => { key, params } | null — write your own and its key is translated like the built-ins:
ts
const strong: Rule = (v) => /[A-Z]/.test(String(v ?? '')) ? null : { key: 'app.validation.uppercase' };required also fails for an unchecked checkbox (false).
API
Form
<ThlForm> · import { ThlForm } from '@thl-ui/vue'
| Prop | Type | Default |
|---|---|---|
layout | string | "vertical" |
bordered | boolean | — |
values | object | — |
Events: submit
Slots: default
Field
<ThlField> · import { ThlField } from '@thl-ui/vue'
| Prop | Type | Default |
|---|---|---|
label | string | — |
help | string | — |
error | string | — |
required | boolean | — |
name | string | — |
value | any | — |
rules | array | — |
status | string | — |
for | string | — |
Slots: default
FormActions
<ThlFormActions> · import { ThlFormActions } from '@thl-ui/vue'
| Prop | Type | Default |
|---|
Slots: default