0
# Form Components
1
2
Comprehensive form controls for building interactive forms with validation, user input, and data selection. These components provide the foundation for mobile form interfaces.
3
4
## Capabilities
5
6
### Field
7
8
Primary text input component with extensive customization and validation support.
9
10
```typescript { .api }
11
import { Field } from 'vant';
12
13
interface FieldProps {
14
/** Input value */
15
modelValue?: string | number;
16
/** Input type */
17
type?: 'text' | 'number' | 'password' | 'textarea' | 'tel' | 'digit' | 'email' | 'url' | 'search';
18
/** Input name */
19
name?: string;
20
/** Field label */
21
label?: string;
22
/** Placeholder text */
23
placeholder?: string;
24
/** Left icon */
25
leftIcon?: string;
26
/** Right icon */
27
rightIcon?: string;
28
/** Disabled state */
29
disabled?: boolean;
30
/** Readonly state */
31
readonly?: boolean;
32
/** Required field marker */
33
required?: boolean;
34
/** Show clear button */
35
clearable?: boolean;
36
/** Clickable field */
37
clickable?: boolean;
38
/** Auto resize for textarea */
39
autosize?: boolean | { maxHeight?: number; minHeight?: number };
40
/** Maximum input length */
41
maxlength?: number | string;
42
/** Show word limit */
43
showWordLimit?: boolean;
44
/** Error message */
45
errorMessage?: string;
46
/** Formatter function */
47
formatter?: (value: string) => string;
48
/** Format trigger timing */
49
formatTrigger?: 'onChange' | 'onBlur';
50
/** Auto focus */
51
autofocus?: boolean;
52
/** Input align */
53
inputAlign?: 'left' | 'center' | 'right';
54
/** Label width */
55
labelWidth?: string | number;
56
/** Label align */
57
labelAlign?: 'left' | 'center' | 'right';
58
/** Label class */
59
labelClass?: string;
60
/** Input class */
61
inputClass?: string;
62
/** Size */
63
size?: 'large' | 'normal';
64
/** Border */
65
border?: boolean;
66
/** Center content */
67
center?: boolean;
68
/** Is link style */
69
isLink?: boolean;
70
/** Arrow direction */
71
arrowDirection?: 'left' | 'up' | 'down' | 'right';
72
}
73
74
// Events
75
interface FieldEvents {
76
'update:modelValue': (value: string) => void;
77
click: (event: MouseEvent) => void;
78
focus: (event: FocusEvent) => void;
79
blur: (event: FocusEvent) => void;
80
clear: (event: MouseEvent) => void;
81
'click-input': (event: MouseEvent) => void;
82
'click-left-icon': (event: MouseEvent) => void;
83
'click-right-icon': (event: MouseEvent) => void;
84
}
85
```
86
87
**Usage Example:**
88
89
```vue
90
<template>
91
<van-form @submit="onSubmit">
92
<van-cell-group inset>
93
<van-field
94
v-model="form.username"
95
name="username"
96
label="Username"
97
placeholder="Enter username"
98
:rules="[{ required: true, message: 'Username is required' }]"
99
/>
100
101
<van-field
102
v-model="form.password"
103
type="password"
104
name="password"
105
label="Password"
106
placeholder="Enter password"
107
:rules="[{ required: true, message: 'Password is required' }]"
108
/>
109
110
<van-field
111
v-model="form.phone"
112
type="tel"
113
name="phone"
114
label="Phone"
115
placeholder="Enter phone number"
116
maxlength="11"
117
show-word-limit
118
/>
119
</van-cell-group>
120
121
<div style="margin: 16px;">
122
<van-button round block type="primary" native-type="submit">
123
Submit
124
</van-button>
125
</div>
126
</van-form>
127
</template>
128
129
<script setup lang="ts">
130
import { reactive } from 'vue';
131
import { Field, Form, CellGroup, Button } from 'vant';
132
133
const form = reactive({
134
username: '',
135
password: '',
136
phone: ''
137
});
138
139
const onSubmit = (values: any) => {
140
console.log('Form submitted:', values);
141
};
142
</script>
143
```
144
145
### Form
146
147
Form container component with validation and submission handling.
148
149
```typescript { .api }
150
import { Form } from 'vant';
151
152
interface FormProps {
153
/** Colon after label */
154
colon?: boolean;
155
/** Disabled state */
156
disabled?: boolean;
157
/** Readonly state */
158
readonly?: boolean;
159
/** Show error */
160
showError?: boolean;
161
/** Show error message */
162
showErrorMessage?: boolean;
163
/** Submit on enter */
164
submitOnEnter?: boolean;
165
/** Validate first error only */
166
validateFirst?: boolean;
167
/** Validate trigger */
168
validateTrigger?: 'onBlur' | 'onChange' | 'onSubmit';
169
/** Scroll to error */
170
scrollToError?: boolean;
171
}
172
173
interface FormInstance {
174
submit: () => void;
175
validate: (name?: string) => Promise<any>;
176
resetValidation: (name?: string) => void;
177
getValidationStatus: () => boolean;
178
scrollToField: (name: string) => void;
179
}
180
```
181
182
### Checkbox
183
184
Checkbox component for multiple selections with group support.
185
186
```typescript { .api }
187
import { Checkbox, CheckboxGroup } from 'vant';
188
189
interface CheckboxProps {
190
/** Checked state */
191
modelValue?: boolean;
192
/** Checkbox name */
193
name?: string | number;
194
/** Checkbox shape */
195
shape?: 'square' | 'round';
196
/** Disabled state */
197
disabled?: boolean;
198
/** Label disabled */
199
labelDisabled?: boolean;
200
/** Label position */
201
labelPosition?: 'left' | 'right';
202
/** Icon size */
203
iconSize?: string | number;
204
/** Checked color */
205
checkedColor?: string;
206
/** Bind object value in group */
207
bindGroup?: boolean;
208
/** Indeterminate state */
209
indeterminate?: boolean;
210
}
211
212
interface CheckboxGroupProps {
213
/** Selected values */
214
modelValue?: any[];
215
/** Disabled state */
216
disabled?: boolean;
217
/** Maximum selections */
218
max?: number | string;
219
/** Direction */
220
direction?: 'horizontal' | 'vertical';
221
/** Icon size */
222
iconSize?: string | number;
223
/** Checked color */
224
checkedColor?: string;
225
}
226
```
227
228
### Radio
229
230
Radio button component for single selections.
231
232
```typescript { .api }
233
import { Radio, RadioGroup } from 'vant';
234
235
interface RadioProps {
236
/** Radio value */
237
name?: any;
238
/** Checked state */
239
modelValue?: any;
240
/** Disabled state */
241
disabled?: boolean;
242
/** Label disabled */
243
labelDisabled?: boolean;
244
/** Label position */
245
labelPosition?: 'left' | 'right';
246
/** Icon size */
247
iconSize?: string | number;
248
/** Checked color */
249
checkedColor?: string;
250
/** Radio shape */
251
shape?: 'square' | 'round';
252
}
253
254
interface RadioGroupProps {
255
/** Selected value */
256
modelValue?: any;
257
/** Disabled state */
258
disabled?: boolean;
259
/** Direction */
260
direction?: 'horizontal' | 'vertical';
261
/** Icon size */
262
iconSize?: string | number;
263
/** Checked color */
264
checkedColor?: string;
265
}
266
```
267
268
### Switch
269
270
Toggle switch component for binary states.
271
272
```typescript { .api }
273
import { Switch } from 'vant';
274
275
interface SwitchProps {
276
/** Switch state */
277
modelValue?: boolean;
278
/** Loading state */
279
loading?: boolean;
280
/** Disabled state */
281
disabled?: boolean;
282
/** Switch size */
283
size?: string | number;
284
/** Active color */
285
activeColor?: string;
286
/** Inactive color */
287
inactiveColor?: string;
288
/** Active value */
289
activeValue?: any;
290
/** Inactive value */
291
inactiveValue?: any;
292
}
293
```
294
295
### Stepper
296
297
Numeric stepper component for incrementing/decrementing values.
298
299
```typescript { .api }
300
import { Stepper } from 'vant';
301
302
interface StepperProps {
303
/** Current value */
304
modelValue?: number | string;
305
/** Minimum value */
306
min?: number | string;
307
/** Maximum value */
308
max?: number | string;
309
/** Default value */
310
defaultValue?: number | string;
311
/** Step size */
312
step?: number | string;
313
/** Input name */
314
name?: string;
315
/** Integer only */
316
integer?: boolean;
317
/** Disabled state */
318
disabled?: boolean;
319
/** Disable plus button */
320
disablePlus?: boolean;
321
/** Disable minus button */
322
disableMinus?: boolean;
323
/** Disable input */
324
disableInput?: boolean;
325
/** Readonly input */
326
readonly?: boolean;
327
/** Input width */
328
inputWidth?: string | number;
329
/** Button size */
330
buttonSize?: string | number;
331
/** Show plus button */
332
showPlus?: boolean;
333
/** Show minus button */
334
showMinus?: boolean;
335
/** Show input */
336
showInput?: boolean;
337
/** Long press */
338
longPress?: boolean;
339
/** Allow empty */
340
allowEmpty?: boolean;
341
/** Placeholder */
342
placeholder?: string;
343
}
344
```
345
346
### Picker
347
348
Multi-column picker component for selecting values from predefined options.
349
350
```typescript { .api }
351
import { Picker } from 'vant';
352
353
interface PickerProps {
354
/** Picker columns */
355
columns?: PickerColumn[] | PickerColumn[][];
356
/** Default selected indexes */
357
defaultIndex?: number | number[];
358
/** Toolbar position */
359
toolbarPosition?: 'top' | 'bottom';
360
/** Show toolbar */
361
showToolbar?: boolean;
362
/** Title */
363
title?: string;
364
/** Confirm button text */
365
confirmButtonText?: string;
366
/** Cancel button text */
367
cancelButtonText?: string;
368
/** Loading state */
369
loading?: boolean;
370
/** Readonly state */
371
readonly?: boolean;
372
/** Item height */
373
itemHeight?: number | string;
374
/** Visible item count */
375
visibleItemCount?: number | string;
376
/** Swipe duration */
377
swipeDuration?: number | string;
378
}
379
380
interface PickerColumn {
381
text?: string;
382
value?: string | number;
383
disabled?: boolean;
384
children?: PickerColumn[];
385
className?: string;
386
}
387
388
interface PickerInstance {
389
confirm: () => void;
390
getSelectedOptions: () => PickerColumn[];
391
setColumnValues: (columnIndex: number, values: PickerColumn[]) => void;
392
setColumnValue: (columnIndex: number, value: string | number) => void;
393
setColumnIndex: (columnIndex: number, optionIndex: number) => void;
394
getColumnValue: (columnIndex: number) => string | number;
395
getColumnIndex: (columnIndex: number) => number;
396
getValues: () => (string | number)[];
397
setValues: (values: (string | number)[]) => void;
398
getIndexes: () => number[];
399
setIndexes: (indexes: number[]) => void;
400
}
401
```
402
403
### DatePicker
404
405
Date selection component with various modes and customization options.
406
407
```typescript { .api }
408
import { DatePicker } from 'vant';
409
410
interface DatePickerProps {
411
/** Selected date */
412
modelValue?: Date;
413
/** Picker type */
414
type?: 'date' | 'time' | 'datetime' | 'datehour' | 'month-day' | 'year-month';
415
/** Title */
416
title?: string;
417
/** Confirm button text */
418
confirmButtonText?: string;
419
/** Cancel button text */
420
cancelButtonText?: string;
421
/** Show toolbar */
422
showToolbar?: boolean;
423
/** Loading state */
424
loading?: boolean;
425
/** Readonly state */
426
readonly?: boolean;
427
/** Filter options */
428
filter?: (type: string, values: string[]) => string[];
429
/** Formatter */
430
formatter?: (type: string, value: string) => string;
431
/** Columns order */
432
columnsOrder?: string[];
433
/** Min date */
434
minDate?: Date;
435
/** Max date */
436
maxDate?: Date;
437
}
438
```
439
440
### TimePicker
441
442
Time selection component for hour, minute, and second selection.
443
444
```typescript { .api }
445
import { TimePicker } from 'vant';
446
447
interface TimePickerProps {
448
/** Selected time */
449
modelValue?: string;
450
/** Title */
451
title?: string;
452
/** Confirm button text */
453
confirmButtonText?: string;
454
/** Cancel button text */
455
cancelButtonText?: string;
456
/** Show toolbar */
457
showToolbar?: boolean;
458
/** Loading state */
459
loading?: boolean;
460
/** Readonly state */
461
readonly?: boolean;
462
/** Filter options */
463
filter?: (type: string, values: string[]) => string[];
464
/** Formatter */
465
formatter?: (type: string, value: string) => string;
466
/** Columns order */
467
columnsOrder?: string[];
468
/** Min hour */
469
minHour?: number | string;
470
/** Max hour */
471
maxHour?: number | string;
472
/** Min minute */
473
minMinute?: number | string;
474
/** Max minute */
475
maxMinute?: number | string;
476
/** Min second */
477
minSecond?: number | string;
478
/** Max second */
479
maxSecond?: number | string;
480
}
481
```
482
483
### Calendar
484
485
Calendar component for date range selection with various display modes.
486
487
```typescript { .api }
488
import { Calendar } from 'vant';
489
490
interface CalendarProps {
491
/** Calendar type */
492
type?: 'single' | 'multiple' | 'range';
493
/** Selected date(s) */
494
modelValue?: Date | Date[] | null;
495
/** Show calendar */
496
show?: boolean;
497
/** Title */
498
title?: string;
499
/** Subtitle */
500
subtitle?: string;
501
/** Color */
502
color?: string;
503
/** Min date */
504
minDate?: Date;
505
/** Max date */
506
minDate?: Date;
507
/** Default date */
508
defaultDate?: Date | Date[] | null;
509
/** Row height */
510
rowHeight?: number | string;
511
/** Formatter */
512
formatter?: (day: CalendarDay) => CalendarDay;
513
/** Poppable */
514
poppable?: boolean;
515
/** Lazy render */
516
lazyRender?: boolean;
517
/** Show mark */
518
showMark?: boolean;
519
/** Show title */
520
showTitle?: boolean;
521
/** Show subtitle */
522
showSubtitle?: boolean;
523
/** Show confirm */
524
showConfirm?: boolean;
525
/** Readonly */
526
readonly?: boolean;
527
/** Confirm text */
528
confirmText?: string;
529
/** Confirm disabled text */
530
confirmDisabledText?: string;
531
/** First day of week */
532
firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
533
}
534
535
interface CalendarDay {
536
date?: Date;
537
type?: string;
538
text?: string | number;
539
topInfo?: string;
540
bottomInfo?: string;
541
disabled?: boolean;
542
className?: string;
543
}
544
```
545
546
### Rate
547
548
Star rating component for user feedback and ratings.
549
550
```typescript { .api }
551
import { Rate } from 'vant';
552
553
interface RateProps {
554
/** Current rate */
555
modelValue?: number;
556
/** Star count */
557
count?: number | string;
558
/** Star size */
559
size?: number | string;
560
/** Gutter between stars */
561
gutter?: number | string;
562
/** Star color */
563
color?: string;
564
/** Void star color */
565
voidColor?: string;
566
/** Disabled star color */
567
disabledColor?: string;
568
/** Star icon */
569
icon?: string;
570
/** Void star icon */
571
voidIcon?: string;
572
/** Icon prefix */
573
iconPrefix?: string;
574
/** Allow half star */
575
allowHalf?: boolean;
576
/** Readonly state */
577
readonly?: boolean;
578
/** Disabled state */
579
disabled?: boolean;
580
/** Touchable */
581
touchable?: boolean;
582
}
583
```
584
585
### Uploader
586
587
File upload component with preview and progress tracking.
588
589
```typescript { .api }
590
import { Uploader } from 'vant';
591
592
interface UploaderProps {
593
/** File list */
594
modelValue?: UploaderFileListItem[];
595
/** Accept file types */
596
accept?: string;
597
/** Maximum file count */
598
maxCount?: number | string;
599
/** Maximum file size */
600
maxSize?: number | string;
601
/** Preview size */
602
previewSize?: number | string;
603
/** Preview image */
604
previewImage?: boolean;
605
/** Preview full image */
606
previewFullImage?: boolean;
607
/** Multiple selection */
608
multiple?: boolean;
609
/** Disabled state */
610
disabled?: boolean;
611
/** Readonly state */
612
readonly?: boolean;
613
/** Deletable */
614
deletable?: boolean;
615
/** Show upload */
616
showUpload?: boolean;
617
/** Capture */
618
capture?: string;
619
/** After read */
620
afterRead?: (file: UploaderFileListItem | UploaderFileListItem[]) => void;
621
/** Before read */
622
beforeRead?: (file: File | File[]) => boolean | Promise<File | File[]>;
623
/** Before delete */
624
beforeDelete?: (file: UploaderFileListItem, detail: { name: string; index: number }) => boolean | Promise<boolean>;
625
/** Upload area text */
626
uploadText?: string;
627
/** Upload icon */
628
uploadIcon?: string;
629
/** Image fit */
630
imageFit?: string;
631
/** Result type */
632
resultType?: 'file' | 'text' | 'dataUrl';
633
}
634
635
interface UploaderFileListItem {
636
url?: string;
637
file?: File;
638
content?: string;
639
status?: 'uploading' | 'success' | 'failed';
640
message?: string;
641
name?: string;
642
isImage?: boolean;
643
deletable?: boolean;
644
previewSize?: number | string;
645
imageFit?: string;
646
}
647
```
648
649
### Form
650
651
Form container component providing validation and field management.
652
653
```typescript { .api }
654
import { Form } from 'vant';
655
656
interface FormProps {
657
/** Colon after label */
658
colon?: boolean;
659
/** Disabled state */
660
disabled?: boolean;
661
/** Label width */
662
labelWidth?: string | number;
663
/** Label align */
664
labelAlign?: 'left' | 'center' | 'right';
665
/** Input align */
666
inputAlign?: 'left' | 'center' | 'right';
667
/** Scroll to error field */
668
scrollToError?: boolean;
669
/** Validate first error only */
670
validateFirst?: boolean;
671
/** Submit on enter */
672
submitOnEnter?: boolean;
673
/** Show error */
674
showError?: boolean;
675
/** Show error message */
676
showErrorMessage?: boolean;
677
/** Validate trigger */
678
validateTrigger?: 'onBlur' | 'onChange' | 'onSubmit';
679
}
680
681
// Events
682
interface FormEvents {
683
/** Triggered when form is submitted */
684
submit: (values: Record<string, any>) => void;
685
/** Triggered when form validation fails */
686
failed: (errorInfo: FormErrorInfo) => void;
687
}
688
689
// Instance methods
690
interface FormInstance {
691
/** Submit form */
692
submit: () => void;
693
/** Validate all fields */
694
validate: (name?: string | string[]) => Promise<void>;
695
/** Reset all fields to initial values */
696
resetValidation: (name?: string | string[]) => void;
697
/** Get field values */
698
getValues: () => Record<string, any>;
699
/** Scroll to field */
700
scrollToField: (name: string, options?: ScrollIntoViewOptions) => void;
701
}
702
703
interface FormErrorInfo {
704
name: string;
705
message: string;
706
}
707
```
708
709
**Usage Example:**
710
711
```vue
712
<template>
713
<van-form @submit="onSubmit" @failed="onFailed">
714
<van-field
715
v-model="username"
716
name="username"
717
label="Username"
718
placeholder="Username"
719
:rules="[{ required: true, message: 'Please fill in username' }]"
720
/>
721
<van-field
722
v-model="password"
723
type="password"
724
name="password"
725
label="Password"
726
placeholder="Password"
727
:rules="[{ required: true, message: 'Please fill in password' }]"
728
/>
729
<div style="margin: 16px;">
730
<van-button round block type="primary" native-type="submit">
731
Submit
732
</van-button>
733
</div>
734
</van-form>
735
</template>
736
737
<script setup lang="ts">
738
import { ref } from 'vue';
739
import { Form, Field, Button } from 'vant';
740
741
const username = ref('');
742
const password = ref('');
743
744
const onSubmit = (values: any) => {
745
console.log('submit', values);
746
};
747
748
const onFailed = (errorInfo: any) => {
749
console.log('failed', errorInfo);
750
};
751
</script>
752
```
753
754
### Cascader
755
756
Cascading selection component for hierarchical data selection.
757
758
```typescript { .api }
759
import { Cascader } from 'vant';
760
761
interface CascaderProps {
762
/** Options data */
763
options: CascaderOption[];
764
/** Selected value */
765
modelValue?: string | number;
766
/** Field names mapping */
767
fieldNames?: CascaderFieldNames;
768
/** Placeholder */
769
placeholder?: string;
770
/** Active color */
771
activeColor?: string;
772
/** Show header */
773
showHeader?: boolean;
774
/** Title */
775
title?: string;
776
/** Close icon */
777
closeIcon?: string;
778
/** Swipeable tabs */
779
swipeable?: boolean;
780
/** Closeable */
781
closeable?: boolean;
782
}
783
784
interface CascaderOption {
785
text: string;
786
value: string | number;
787
color?: string;
788
disabled?: boolean;
789
children?: CascaderOption[];
790
}
791
792
interface CascaderFieldNames {
793
text?: string;
794
value?: string;
795
children?: string;
796
}
797
798
// Events
799
interface CascaderEvents {
800
/** Triggered when selection changes */
801
change: (value: string | number, selectedOptions: CascaderOption[], selectedItems: CascaderOption[]) => void;
802
/** Triggered when cascade item is clicked */
803
clickTab: (tabIndex: number, title: string) => void;
804
/** Triggered when close button is clicked */
805
close: () => void;
806
/** Triggered when selection is finished */
807
finish: (selectedOptions: CascaderOption[]) => void;
808
}
809
```
810
811
**Usage Example:**
812
813
```vue
814
<template>
815
<van-cascader
816
v-model="cascaderValue"
817
title="Select Area"
818
:options="options"
819
@change="onChange"
820
@finish="onFinish"
821
/>
822
</template>
823
824
<script setup lang="ts">
825
import { ref } from 'vue';
826
import { Cascader } from 'vant';
827
828
const cascaderValue = ref('');
829
const options = [
830
{
831
text: 'Zhejiang',
832
value: '330000',
833
children: [
834
{
835
text: 'Hangzhou',
836
value: '330100',
837
children: [
838
{ text: 'Xihu District', value: '330106' },
839
{ text: 'Yuhang District', value: '330110' },
840
],
841
},
842
],
843
},
844
];
845
846
const onChange = (value: any, selectedOptions: any) => {
847
console.log('change', value, selectedOptions);
848
};
849
850
const onFinish = (selectedOptions: any) => {
851
console.log('finish', selectedOptions);
852
};
853
</script>
854
```
855
856
### Signature
857
858
Signature pad component for capturing handwritten signatures.
859
860
```typescript { .api }
861
import { Signature } from 'vant';
862
863
interface SignatureProps {
864
/** Pen color */
865
penColor?: string;
866
/** Line width */
867
lineWidth?: number;
868
/** Background color */
869
backgroundColor?: string;
870
/** Clear button text */
871
clearButtonText?: string;
872
/** Confirm button text */
873
confirmButtonText?: string;
874
}
875
876
// Events
877
interface SignatureEvents {
878
/** Triggered when signature is submitted */
879
submit: (data: { image: string; canvas: HTMLCanvasElement }) => void;
880
/** Triggered when signature is cleared */
881
clear: () => void;
882
/** Triggered when signature starts */
883
start: () => void;
884
/** Triggered when signature ends */
885
end: () => void;
886
/** Triggered when signing */
887
signing: (event: TouchEvent) => void;
888
}
889
890
// Instance methods
891
interface SignatureInstance {
892
/** Resize signature pad */
893
resize: () => void;
894
/** Clear signature */
895
clear: () => void;
896
/** Get signature data */
897
submit: () => void;
898
}
899
```
900
901
**Usage Example:**
902
903
```vue
904
<template>
905
<div>
906
<van-signature
907
@submit="onSubmit"
908
@clear="onClear"
909
:line-width="3"
910
pen-color="#000"
911
/>
912
</div>
913
</template>
914
915
<script setup lang="ts">
916
import { Signature } from 'vant';
917
918
const onSubmit = (data: any) => {
919
console.log('Signature submitted:', data.image);
920
};
921
922
const onClear = () => {
923
console.log('Signature cleared');
924
};
925
</script>
926
```