Form Components
Form containers, various input controls and selectors. Each example shows the formatted, highlighted TokUI DSL on the left and the live render on the right; click "Edit" to modify it instantly. Every form control's label renders a required asterisk when req is set.
Form Container form
Wraps a group of form controls. On submit, triggers the sub: handler or the native act submission.
| Prop | Meaning | Example |
|---|---|---|
act | Submit URL | act:/api/save |
mtd | Submit method | mtd:post |
sub | Submit handler name | sub:onSubmit |
clk | Generic event handler name | clk:onFormClick |
The handler referenced by
sub:must be pre-registered viaTokUI.registerHandler(name, fn); on abtn, usesub:xxxto trigger form submission.
Value-Change Reporting (change event)
Form controls report user value changes in real time to a pre-registered handler via on:"change:handler" (double quotes required) — the "user → AI" interaction loop:
[input n:city l:City on:"change:onCityChange"]
[switch l:Notifications n:notify on:"change:onNotifyChange"]- Input debounce:
input/pwd/textarea/numinputreport 300ms after typing stops; override the milliseconds withdb:(e.g.db:500). - Fire on change:
select/radio/checkbox/switch/slider/rate/picker/transfer/cascader/datepickerfamily /input-tagreport immediately when the value changes. - upload: reports
changewhen files are selected / removed, with detail{value: filename array, name}. - detail shape: handler signature
(detail, event, element), withdetail={value, name}. - Unified outlet: every interaction also goes to
new TokUI({ onEvent })'sonEvent('component', { type, id, event, detail })— the host can listen to everything without anyon:declaration.
For the full event list see DSL Syntax · Interaction event reporting.
DSL Validation Rules
input / pwd / textarea / select support declarative validation via rule: + msg:, enforced uniformly on submit (all sub / t:submit paths). Failures block submission, mark the field red with a hint, and focus the first invalid field:
[input n:email l:"Email" rule:"required|email"]
[input n:code l:"Code" rule:"required|len:6" msg:"Please enter the 6-digit code"]
[select n:city l:"City" rule:"required" opt:"bj:Beijing;sh:Shanghai"]- Rules are pipe-separated and short-circuit in order:
requiredemailurlnumberlen:N(exact length)min:Nmax:N(character count)re:regex. - Empty values skip non-
requiredrules (HTML5 semantics: empty + not required = valid). msg:customizes the error message (built-in i18n text by default); unknown rule names / invalid regexes are skipped with aconsole.warn.- Combined with
live: real-time validation on blur, with instant re-check while typing in the error state. reqonselectwrites the nativerequiredattribute (except multi-select, where the semantics don't fit).
Input input
Single-line text input, self-closing. l for label, ph for placeholder, t for native type, val for initial value.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:姓名 |
ph | Placeholder hint | ph:"请输入姓名" |
t | Native input type | t:email |
n | Field name | n:username |
val | Default value | val:Tom |
id | Element ID | id:username |
w | Width | w:240 |
hint | Hint text | hint:6~16 个字符 |
search | Search style | search |
rule / msg | DSL validation rules / custom error message (see DSL Validation Rules) | `rule:"required |
sug | Input-suggestion data-source handler | sug:onSuggest |
req / dis / ro | Required / Disabled / Read-only | req |
Variants: error / success (validation states), sm / lg (sizes), underline (underline style), pill (rounded).
Input suggestions (sug):
sug:data-source-handlerenables a suggestion dropdown —fn({value})returns an array or a Promise (items are strings or{v, tx}); navigate with ↑↓ / Enter / Esc, and selecting fires thechangereport.
Password pwd
Password input with show/hide toggle, self-closing. Same props as input, plus toggle to control whether plain text can be revealed.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:密码 |
ph | Placeholder hint | ph:"至少 6 位" |
toggle | Show/hide toggle button | toggle |
req / dis | Required / Disabled | req |
v | Variant (same as input) | v:error |
Textarea textarea
Multi-line text input container. rows for initial row count, maxlen for max character count, auto for auto-growing height.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:描述 |
ph | Placeholder hint | ph:"请输入描述" |
rows | Initial rows | rows:4 |
maxrows | Max rows (auto mode) | maxrows:8 |
maxlen | Max character count | maxlen:200 |
auto | Auto-grow height | auto |
tx | Default content | tx:"默认文本" |
req / dis / ro | Required / Disabled / Read-only | req |
Dropdown select / opt
select is a container; opt are child option nodes. multi for multi-select, req for required.
| Prop | Meaning | Applies to |
|---|---|---|
l | Label | select |
ph | Placeholder hint | select |
multi | Multi-select | select |
n | Field name | select |
req | Required | select |
v | Variant | select |
tx | Option text | opt |
v | Option value | opt |
chk | Default selected | opt |
select variants: error / success.
Radio Group radio
radio is a container; opt are child option nodes. Options sharing the same n are mutually exclusive. Two forms: container ([opt] children) or opt:"..." shorthand (self-closing, no [/radio] needed).
| Prop | Meaning | Applies to |
|---|---|---|
l | Group label | radio |
n | Field name (shared by group, submission key) | radio |
id | Group ID | radio |
v | inline (label beside control) / vertical (options stacked, left-aligned) | radio |
opt | Shorthand option string opt:"v:label;v:label" (self-closing form) | radio |
tx | Option text | opt |
v | Option value | opt |
chk | Default selected | opt |
Checkbox checkbox
Three modes (auto-detected by presence of opt / multi):
| Mode | Detection | Syntax | Submitted value |
|---|---|---|---|
| Single boolean | no opt, no multi (self-closing) | [checkbox l:同意协议 n:agree chk] | boolean (checked = agree present) |
| Shorthand multi | has opt (self-closing) | [checkbox n:tag l:标签 opt:"1:A;2:B;3:C"] | data.tag = array |
| Container multi | has multi (container) | [checkbox n:tag l:标签 multi][opt v:1 tx:A chk][/checkbox] | data.tag = array |
| Prop | Meaning | Applies to |
|---|---|---|
l | Label | checkbox |
n | Field name (multi-select submission key) | checkbox |
opt | Shorthand option string (self-closing multi) | checkbox |
multi | Marks container multi mode (needs [/checkbox]) | checkbox |
v | inline/vertical | checkbox |
chk | Default checked / selected | checkbox / opt |
dis | Disabled | checkbox |
Multi-select submission uses native FormData; same-n values auto-aggregate into an array (e.g. checking A and C → data.tag = ["1","3"]). Single-boolean and shorthand-multi are self-closing — do NOT write [/checkbox]; only multi container-multi needs [/checkbox].
Submit-button placement (get this wrong → no data): put it inside the form
[form id:F sub:H]...[btn tx:Submit clk:H][/form](clk auto-collects the owning form); OR outside the form but with explicitform:FORM_IDbinding[btn tx:Submit form:F clk:H]. A button outside the form with noform:ID→ handler receivesnull.
Switch switch
Self-closing. chk to turn on, clk for the toggle callback.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:邮件通知 |
chk | Default on | chk |
dis | Disabled | dis |
clk | Toggle handler name | clk:onToggle |
n | Field name | n:notify |
v | Value | v:1 |
id | Element ID | id:notify |
Variants: sm / lg.
Slider slider
Self-closing. min/max/step for range and step, v for current value.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:音量 |
min | Minimum value | min:0 |
max | Maximum value | max:100 |
step | Step | step:5 |
v | Current value | v:60 |
dis | Disabled | dis |
clk | Drag callback | clk:onSlide |
n | Field name | n:volume |
id | Element ID | id:volume |
range | Dual-thumb range mode | range |
marks | Tick labels (value:label, comma-separated) | marks:"0:免费,50:标准" |
Variants: sm / lg.
Range & marks:
rangeselects an interval with two thumbs (v:"20,60"), andchangereports{value: [min, max]};marks:"0:免费,50:标准,100:旗舰"renders tick labels.
Rate rate
Self-closing. max for max star count, v for current rating, clk for the select callback.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:评分 |
v | Current value | v:4 |
max | Max stars | max:5 |
clk | Select callback | clk:onRate |
dis | Read-only / disabled | dis |
tx | Caption text | tx:很好 |
half | Half-star selection (0.5 steps; clicking the same value again clears it) | half |
Number Input numinput
Self-closing. Number input with increment/decrement buttons; min/max/step constrain the range.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:数量 |
v | Current value | v:1 |
min | Minimum value | min:1 |
max | Maximum value | max:99 |
step | Step | step:1 |
dis | Disabled | dis |
n | Field name | n:qty |
id | Element ID | id:qty |
Button Group btngroup
Container that wraps a set of btns. In form scenarios, commonly used as a multi-button action area (for primary button usage see Basic Components).
| Prop | Meaning | Example |
|---|---|---|
id | Group ID | id:actions |
v | Variant | v:vertical |
Variants: vertical (vertical layout), pill (rounded group).
Picker picker
Container; a richer selection panel than select (with search / multiple columns). multi for multi-select, dis for disabled.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:城市 |
ph | Placeholder hint | ph:"请选择" |
multi | Multi-select | multi |
dis | Disabled | dis |
n | Field name | n:city |
v | Value | v:bj |
id | Element ID | id:city |
Variants: error / success.
Cascader cascader
Container; a multi-level selector that expands level by level (e.g. province/city/district). clk for the select callback.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:地区 |
ph | Placeholder hint | ph:"请选择" |
dis | Disabled | dis |
clk | Select callback | clk:onPick |
v | Value | v:"北京-朝阳" |
n | Field name | n:region |
id | Element ID | id:region |
Variants: error / success.
Upload upload
Self-closing. accept restricts file types, multi for multiple files, max for maximum count.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:附件 |
ph | Placeholder hint | ph:"点击或拖拽上传" |
accept | Allowed types | accept:"image/*" |
multi | Multiple files | multi |
max | Max count | max:5 |
dis | Disabled | dis |
clk | Upload callback | clk:onUpload |
n | Field name | n:file |
id | Element ID | id:file |
u | Upload URL (http(s) / relative paths only; enables auto-transfer) | u:/api/upload |
mtd | Upload method | mtd:post |
Variants: sm / lg.
Transfer layer: with u: set, selected files are automatically uploaded one by one via XHR; each file item shows a progress bar / success ✓ / failure ✗+retry state, and reports the progress {file, percent} / success {file, response} / error {file, error} events. Without u:, selection stays frontend-only (only the change event).
The server can push
[upd id:file act:clear]to clear the selected-file list.
Date Picker datepicker
Self-closing. fmt for date format, v for default value, clk for the select callback.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:出生日期 |
ph | Placeholder hint | ph:"请选择日期" |
fmt | Date format | fmt:yyyy-MM-dd |
v | Default value | v:2026-06-20 |
clk | Select callback | clk:onDate |
dis | Disabled | dis |
n | Field name | n:birthday |
id | Element ID | id:birthday |
range | Range mode (two clicks pick start and end) | range |
Range mode: with
range, two clicks pick the start and end dates; the value format isYYYY-MM-DD ~ YYYY-MM-DD.
Time Picker timepicker
Self-closing. fmt for time format, v for default value.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:开始时间 |
ph | Placeholder hint | ph:"请选择时间" |
fmt | Time format | fmt:HH:mm |
v | Default value | v:09:30 |
clk | Select callback | clk:onTime |
dis | Disabled | dis |
n | Field name | n:time |
id | Element ID | id:time |
Datetime Picker datetimepicker
Self-closing. Combined date + time picker; fmt for custom format.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:预约时间 |
ph | Placeholder hint | ph:"请选择日期时间" |
fmt | Format | fmt:"yyyy-MM-dd HH:mm" |
v | Default value | v:"2026-06-20 09:30" |
clk | Select callback | clk:onDateTime |
dis | Disabled | dis |
n | Field name | n:dt |
id | Element ID | id:dt |
Transfer transfer
Container; a two-column mutually exclusive multi-select mover. tt/tt2 for the two column titles, clk for the move callback.
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:分配角色 |
tt | Left column title | tt:未选 |
tt2 | Right column title | tt2:已选 |
clk | Move callback | clk:onTransfer |
h | Fixed height (inner scroll) | h:240 / h:40vh |
mh | Max height (overrides default 320px) | mh:200 |
dis | Disabled | dis |
n | Field name | n:roles |
id | Element ID | id:roles |
Variants: sm (max 260px) / lg (max 400px). Default max-height 320px; overflowing lists scroll inside (scrollbar transparent by default, grey semi-transparent on hover).
h fixed height and mh max height examples:
Input Tag input-tag
Press Enter to add a tag, click a tag's × to remove it. tags for initial tags, max for maximum count. Self-closing when tags is present; otherwise close with [/input-tag].
| Prop | Meaning | Example |
|---|---|---|
l | Label | l:标签 |
ph | Placeholder hint | ph:"输入后回车添加" |
n | Field name | n:tags |
max | Max count | max:8 |
tags | Initial tags (comma-separated) | tags:"JS,Python" |
dis | Disabled | dis |
Segmented segmented
A lightweight single-choice switcher (the form-control counterpart of tabs). Two forms: the opt shorthand (atomic self-closing) or container mode with opt children (icons, per-option disabled).
| Prop | Meaning | Example |
|---|---|---|
opt | Shorthand option string v:label;... (double quotes required) | opt:"list:列表;grid:宫格" |
v | Currently selected value (combinable with shape variants) | v:"sm,grid" |
n | Field name | n:view |
l | Label | l:视图 |
dis | Disable the whole group | dis |
on | change reports {value,name} | on:"change:h" |
id | Element ID | id:view |
Variants: sm / lg / block (full width) / pill (rounded) / vertical.
Container-mode opt children (fine-grained per-option control):
| Prop | Meaning | Example |
|---|---|---|
v | Option value | v:grid |
tx | Display text | tx:宫格 |
i | Icon character (emoji/symbol) | i:📊 |
chk | Checked by default (v match wins) | chk |
dis | Disable this option | dis |
The server can switch programmatically with
[upd id:view v:grid]; a form reset restores the initial value.
Color Picker color-picker
Self-closing. The picker panel combines a saturation/brightness pick area, a hue slider, a hex input, preset swatches, and a clear action. presets configures the preset colors. When opened, the panel portals to document.body with fixed positioning so it is never clipped by a parent container's overflow; it repositions to follow the anchor on scroll and closes on outside click or Escape.
| Prop | Meaning | Example |
|---|---|---|
v | Initial color (#rrggbb, defaults to #1677ff) | v:#1677ff |
presets | Preset colors (comma-separated hex) | presets:"#f5222d,#fa8c16" |
n | Field name | n:color |
l | Label | l:主题色 |
dis | Disabled | dis |
on | change reports {value,name} | on:"change:h" |
id | Element ID | id:color |
The server can recolor programmatically with
[upd id:color v:#hex]and re-enable with[upd id:color dis:false]; a form reset restores the initial value.
Editable editable
Self-closing inline element. The text carries a dashed underline marking it as editable; clicking enters the editing state: Enter/blur commits, Escape restores (no report).
| Prop | Meaning | Example |
|---|---|---|
tx / v | Initial text | tx:小木屋 |
ph | Placeholder when empty | ph:点击填写 |
n | Field name | n:nick |
dis | Disabled | dis |
on | Commit (value changed) reports {value,name} | on:"change:h" |
id | Element ID | id:ed1 |
The server can rewrite programmatically with
[upd id:ed1 tx:新值](silent) and unlock with[upd id:ed1 dis:false].
For the full DSL syntax (prop shorthands, variant whitelist, streaming render constraints, etc.), see DSL Syntax.