Form
Forma elementlari uchun joylashuv, tekshiruv va holatni boshqarish imkoniga ega forma wrapperi.
<script setup>
const formRef = ref()
const form = reactive({ name: '', email: '', bio: '' })
const rules = {
name: [
{ required: true, message: 'Please enter your name' },
{ min: 2, max: 30, message: 'Name must be 2-30 characters' },
],
email: [
{ required: true, message: 'Please enter your email' },
{ type: 'email', message: 'Please enter a valid email' },
],
}
async function onSubmit() {
const { valid } = await formRef.value.validate()
if (valid) { /* submit */ }
}
</script>
<template>
<VxForm ref="formRef" :model="form" :rules="rules">
<VxFormItem label="Name" field="name">
<VxInput v-model="form.name" />
</VxFormItem>
<VxFormItem label="Email" field="email">
<VxInput v-model="form.email" />
</VxFormItem>
<VxFormItem>
<VxButton @click="onSubmit">Submit</VxButton>
</VxFormItem>
</VxForm>
</template>Horizontal Layout
<template>
<VxForm :model="form" :rules="rules" layout="horizontal" :label-width="120">
<VxFormItem label="Username" field="username">
<VxInput v-model="form.username" />
</VxFormItem>
<VxFormItem label="Password" field="password">
<VxInput v-model="form.password" type="password" />
</VxFormItem>
<VxFormItem label=" ">
<VxButton>Login</VxButton>
</VxFormItem>
</VxForm>
</template>Inline Layout
<template>
<VxForm :model="form" layout="inline">
<VxFormItem label="Search">
<VxInput v-model="form.search" />
</VxFormItem>
<VxFormItem label="Category">
<VxSelect v-model="form.category" :options="options" />
</VxFormItem>
<VxFormItem>
<VxButton>Search</VxButton>
</VxFormItem>
</VxForm>
</template>Label Description
Yorliq yonida ma'lumot ikonkasini tooltip bilan qo'shish uchun description prop dan yoki boyitilgan tarkib uchun #description slot dan foydalaning.
<template>
<!-- Simple text description -->
<VxFormItem label="API Key" description="Your unique API key from the dashboard.">
<VxInput v-model="form.apiKey" />
</VxFormItem>
<!-- Rich content via #description slot -->
<VxFormItem label="Secret">
<template #description>
<div>
<strong>Signing Secret</strong>
<p>Used to verify webhook payloads.</p>
</div>
</template>
<VxInput v-model="form.secret" type="password" />
</VxFormItem>
</template>Type Validators
O'rnatilgan tur validatorlari: email, url, number, integer, float, date, hex, ip, phone, alpha, alphanumeric, string, boolean, array.
const rules = {
email: [
{ required: true, message: 'Required' },
{ type: 'email', message: 'Invalid email format' },
],
url: [{ type: 'url', message: 'Invalid URL' }],
age: [
{ type: 'integer', message: 'Must be a whole number' },
{ min: 1, max: 150, message: 'Age must be 1-150' },
],
ip: [{ type: 'ip', message: 'Invalid IP address' }],
hex: [{ type: 'hex', message: 'Invalid hex color' }],
phone: [{ type: 'phone', message: 'Invalid phone number' }],
}String Constraints
Satr tekshiruvi uchun pattern, enum, startsWith, endsWith, contains va alpha/alphanumeric turlaridan foydalaning.
const rules = {
code: [
{ required: true, message: 'Required' },
{ pattern: /^[A-Z]{2,3}-\d{3,4}$/, message: 'Format: XX-000 or XXX-0000' },
],
slug: [
{ type: 'alphanumeric', message: 'Only letters and numbers' },
],
tag: [
{ startsWith: '#', message: 'Must start with #' },
{ min: 2, message: 'At least 2 characters' },
],
domain: [
{ endsWith: '.com', message: 'Must end with .com' },
],
role: [
{ enum: ['admin', 'editor', 'viewer'], message: 'Must be admin, editor, or viewer' },
],
}Cross-Field Validation
Maydonlarni solishtirish uchun same va different, substring tekshiruvi uchun contains dan foydalaning.
const rules = {
password: [
{ required: true, message: 'Password is required' },
{ min: 8, message: 'At least 8 characters' },
{ contains: '!', message: 'Must contain !' },
],
confirm: [
{ required: true, message: 'Please confirm' },
{ same: 'password', message: 'Passwords do not match' },
],
newEmail: [
{ required: true, message: 'New email is required' },
{ type: 'email', message: 'Invalid email' },
{ different: 'currentEmail', message: 'Must differ from current email' },
],
}Async Validator
Validatorlar Promise qaytarishi mumkin. Foydalanuvchi nomining mavjudligi kabi server tomonidagi tekshiruvlar uchun foydali.
const rules = {
username: [
{ required: true, message: 'Username is required' },
{ type: 'alpha', message: 'Letters only' },
{ min: 3, max: 20, message: '3-20 characters' },
{
validator: async (value) => {
const taken = await checkUsername(value)
if (taken) return 'Username is already taken'
return true
},
trigger: 'blur',
},
],
}Reset & Clear Validation
<script setup>
const formRef = ref()
</script>
<template>
<VxForm ref="formRef" :model="form" :rules="rules">
...
<VxButton @click="formRef.validate()">Validate</VxButton>
<VxButton @click="formRef.clearValidation()">Clear Errors</VxButton>
<VxButton @click="formRef.resetFields()">Reset</VxButton>
</VxForm>
</template>Disabled
<template>
<VxForm :model="form" disabled>
<VxFormItem label="Name"><VxInput v-model="form.name" /></VxFormItem>
<VxFormItem label="Email"><VxInput v-model="form.email" /></VxFormItem>
</VxForm>
</template>Horizontal Example
<script setup>
const formRef = ref()
const form = reactive({
firstName: '', lastName: '', email: '',
role: '', newsletter: false, notes: '',
})
const rules = {
firstName: { required: true, message: 'First name is required' },
lastName: { required: true, message: 'Last name is required' },
email: [
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Invalid email format' },
],
role: { required: true, message: 'Please select a role' },
}
</script>
<template>
<VxForm ref="formRef" :model="form" :rules="rules" layout="horizontal" :label-width="120">
<VxFormItem label="First Name" field="firstName">
<VxInput v-model="form.firstName" />
</VxFormItem>
<VxFormItem label="Role" field="role">
<VxSelect v-model="form.role" :options="roles" />
</VxFormItem>
<VxFormItem label="Newsletter">
<VxSwitch v-model="form.newsletter" />
</VxFormItem>
<VxFormItem label=" ">
<VxButton @click="formRef.validate()">Submit</VxButton>
</VxFormItem>
</VxForm>
</template>Registration Form
Har bir maydon uchun bir nechta tekshiruv qoidalari, kuchli parol tekshiruvi, maydonlararo solishtirish va aralash kiritish turlariga ega to'liq misol.
<script setup>
const formRef = ref()
const form = reactive({
name: '', email: '', password: '', confirmPassword: '',
phone: '', website: '', role: '', bio: '', terms: false,
})
const rules = {
name: [
{ required: true, message: 'Full name is required' },
{ min: 2, max: 50, message: '2-50 characters' },
{ type: 'alpha', message: 'Letters only' },
],
email: [
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Enter a valid email address' },
],
password: [
{ required: true, message: 'Password is required' },
{ min: 8, message: 'At least 8 characters' },
{
validator: (v) => {
if (!/[A-Z]/.test(v)) return 'Must contain an uppercase letter'
if (!/[0-9]/.test(v)) return 'Must contain a number'
if (!/[^a-zA-Z0-9]/.test(v)) return 'Must contain a special character'
return true
},
},
],
confirmPassword: [
{ required: true, message: 'Confirm your password' },
{ same: 'password', message: 'Passwords do not match' },
],
phone: [{ type: 'phone', message: 'Enter a valid phone number' }],
website: [
{ type: 'url', message: 'Enter a valid URL' },
{ startsWith: 'https://', message: 'Must use HTTPS' },
],
role: [
{ required: true, message: 'Select a role' },
],
bio: [{ max: 200, message: 'Max 200 characters' }],
terms: [
{ validator: (v) => v === true ? true : 'You must accept the terms' },
],
}
</script>
<template>
<VxForm ref="formRef" :model="form" :rules="rules">
<VxFormItem label="Full Name" field="name">
<VxInput v-model="form.name" />
</VxFormItem>
<VxFormItem label="Email" field="email">
<VxInput v-model="form.email" />
</VxFormItem>
<VxFormItem label="Password" field="password">
<VxInput v-model="form.password" type="password" />
</VxFormItem>
<VxFormItem label="Confirm Password" field="confirmPassword">
<VxInput v-model="form.confirmPassword" type="password" />
</VxFormItem>
<VxFormItem label="Phone" field="phone" help="Optional">
<VxInput v-model="form.phone" />
</VxFormItem>
<VxFormItem label="Website" field="website" help="HTTPS required">
<VxInput v-model="form.website" />
</VxFormItem>
<VxFormItem label="Role" field="role">
<VxSelect v-model="form.role" :options="roles" />
</VxFormItem>
<VxFormItem label="Bio" field="bio" help="Max 200 characters">
<VxInput v-model="form.bio" type="textarea" :rows="3" />
</VxFormItem>
<VxFormItem field="terms">
<VxCheckbox v-model="form.terms" label="I accept the terms and conditions" />
</VxFormItem>
<VxFormItem>
<VxButton @click="formRef.validate()">Register</VxButton>
</VxFormItem>
</VxForm>
</template>Nested Model
user.username kabi ichki obyekt xossalarini bog'lash va tekshirish uchun field da nuqtali yozuvdan foydalaning.
<script setup>
import { ref, reactive } from 'vue'
const formRef = ref()
const form = reactive({
user: { username: '', password: '' },
description: '',
})
// Use dot-notation keys to match nested field paths
const rules = {
'user.username': [
{ required: true, message: 'Username is required' },
{ min: 3, max: 20, message: '3-20 characters' },
{ type: 'alphanumeric', message: 'Letters and numbers only' },
],
'user.password': [
{ required: true, message: 'Password is required' },
{ min: 8, message: 'At least 8 characters' },
{ pattern: /[A-Z]/, message: 'Needs an uppercase letter' },
{ pattern: /[0-9]/, message: 'Needs a number' },
],
description: [
{ max: 200, message: 'Max 200 characters' },
],
}
async function onSubmit() {
const { valid } = await formRef.value.validate()
if (valid) {
console.log('Submitted:', JSON.parse(JSON.stringify(form)))
}
}
</script>
<template>
<VxForm ref="formRef" :model="form" :rules="rules">
<VxFormItem label="Username" field="user.username">
<VxInput v-model="form.user.username" placeholder="Letters and numbers, 3-20 chars" />
</VxFormItem>
<VxFormItem label="Password" field="user.password">
<VxInput v-model="form.user.password" type="password" placeholder="8+ chars, uppercase, number" />
</VxFormItem>
<VxFormItem label="Description" field="description" help="Optional, max 200 characters">
<VxInput v-model="form.description" type="textarea" :rows="3" />
</VxFormItem>
<VxFormItem>
<VxButton @click="onSubmit">Submit</VxButton>
<VxButton variant="outline" @click="formRef.resetFields()">Reset</VxButton>
</VxFormItem>
</VxForm>
</template>Status Icons
Kiritish yonida tekshiruv holati ikonkalarini (spinner, belgi, xoch) ko'rsatish.
<template>
<VxForm ref="formRef" :model="form" :rules="rules" :status-icon="true">
<VxFormItem label="Email" field="email">
<VxInput v-model="form.email" />
</VxFormItem>
</VxForm>
</template>Label Suffix
Barcha yorliqlarga suffiks belgisini (masalan, :) qo'shish.
<template>
<VxForm :model="form" label-suffix=":">
<VxFormItem label="Name"><VxInput v-model="form.name" /></VxFormItem>
<VxFormItem label="Age"><VxInput v-model="form.age" /></VxFormItem>
</VxForm>
</template>Scroll to Error
Tekshiruvdan so'ng xatolikka ega birinchi maydonga avtomatik aylantirish.
<template>
<VxForm ref="formRef" :model="form" :rules="rules" :scroll-to-error="true">
<!-- fields -->
<VxButton @click="formRef.validate()">Validate All</VxButton>
</VxForm>
</template>Show All Errors
Birinchi xatoda to'xtash o'rniga barcha qoida buzilishlarini bir vaqtning o'zida ko'rsatish.
<template>
<VxForm :model="form" :rules="rules" :show-all-errors="true">
<VxFormItem label="Password" field="password">
<VxInput v-model="form.password" />
</VxFormItem>
</VxForm>
</template>
<script setup>
const rules = {
password: [
{ required: true, message: 'Password is required' },
{ min: 8, message: 'At least 8 characters' },
{ pattern: /[A-Z]/, message: 'Must contain an uppercase letter' },
{ pattern: /[0-9]/, message: 'Must contain a number' },
{ pattern: /[^a-zA-Z0-9]/, message: 'Must contain a special character' },
],
}
</script>Loading State
Barcha o'zaro ta'sirlarni o'chirish va yuklash holatini ko'rsatish uchun loading ni o'rnating. disabled bilan birlashtiriladi.
<script setup>
const loading = ref(false)
async function onSubmit() {
loading.value = true
await submitForm()
loading.value = false
}
</script>
<template>
<VxForm :model="form" :loading="loading">
<!-- fields -->
<VxButton @click="onSubmit">Submit</VxButton>
</VxForm>
</template>Dirty Tracking
Formaning o'zgartirilganligini kuzatish. isDirty va dirtyFields ga ref orqali kiring.
<script setup>
const formRef = ref()
const form = reactive({ name: 'John', email: 'john@test.com' })
</script>
<template>
<VxForm ref="formRef" :model="form">
<!-- fields -->
<VxButton :disabled="!formRef?.isDirty">Save Changes</VxButton>
<span>{{ formRef?.isDirty ? `Modified: ${formRef?.dirtyFields}` : 'No changes' }}</span>
</VxForm>
</template>Dependent Field Re-validation
Boshqa maydon o'zgarganda qayta tekshirish uchun FormItem da dependencies prop dan foydalaning. "Parolni tasdiqlash" stsenariylari uchun foydali.
<template>
<VxForm :model="form" :rules="rules">
<VxFormItem label="Password" field="password">
<VxInput v-model="form.password" type="password" />
</VxFormItem>
<VxFormItem label="Confirm" field="confirm" :dependencies="['password']">
<VxInput v-model="form.confirm" type="password" />
</VxFormItem>
</VxForm>
</template>
<script setup>
const rules = {
password: [{ required: true }, { min: 6, message: 'At least 6 characters' }],
confirm: [{ required: true }, { same: 'password', message: 'Passwords do not match' }],
}
</script>Required Mark Position
Majburiy yulduzcha yorliqning chap yoki o'ng tomonida paydo bo'lishini boshqaring.
<template>
<!-- Asterisk on left (default) -->
<VxForm :model="form" :rules="rules" required-mark-position="left">...</VxForm>
<!-- Asterisk on right -->
<VxForm :model="form" :rules="rules" required-mark-position="right">...</VxForm>
</template>Extra & Error Slots
Kiritish ostidagi maslahatlar uchun #extra dan, maxsus xatolik ko'rsatish uchun #error dan foydalaning.
<template>
<VxFormItem label="Password" field="password">
<VxInput v-model="form.password" type="password" />
<template #extra>
<span>Must be 8+ chars with uppercase, number, and special character.</span>
</template>
<template #error="{ errors, first }">
<ul>
<li v-for="e in errors" :key="e">{{ e }}</li>
</ul>
</template>
</VxFormItem>
</template>Props
Form
| Prop | Type | Default | Description |
|---|---|---|---|
model | Record<string, any> | — | Forma ma'lumotlari obyekti |
rules | FormRules | — | Maydon nomi bo'yicha kalitlangan tekshiruv qoidalari |
layout | 'vertical' | 'horizontal' | 'inline' | 'vertical' | Forma joylashuvi |
labelWidth | string | number | — | Gorizontal joylashuv uchun yorliq kengligi |
labelAlign | 'left' | 'right' | 'top' | 'right' | Gorizontal joylashuvda yorliq matnining tekislashi |
labelSuffix | string | '' | Barcha yorliqlarga qo'shilgan suffiks (masalan, :) |
size | 'sm' | 'default' | 'lg' | 'default' | Forma o'lchami |
disabled | boolean | false | Butun formani o'chirish |
loading | boolean | false | Yuklash holati — kursor hodisalarini o'chiradi |
showRequiredMark | boolean | true | Majburiy maydonlarda qizil yulduzchani ko'rsatish |
requiredMarkPosition | 'left' | 'right' | 'left' | Majburiy yulduzchaning joylashuvi |
validateOnChange | boolean | true | Model o'zgarganda avtomatik tekshirish |
validateOnBlur | boolean | true | Maydon fokusini yo'qotganda avtomatik tekshirish |
hideErrorMessage | boolean | false | Barcha xatolik xabarlarini yashirish |
scrollToError | boolean | false | Tekshiruvdan so'ng birinchi xatolikka aylantirish |
statusIcon | boolean | false | Kiritishlar yonida tekshiruv holati ikonkalarini ko'rsatish |
showAllErrors | boolean | false | Faqat birinchisi o'rniga barcha tekshiruv xatolarini ko'rsatish |
FormItem
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | '' | Yorliq matni |
field | string | '' | Maydon nomi (model va rules dagi kalitga mos kelishi kerak) |
rules | FormRule | FormRule[] | — | Maydon darajasidagi qoidalar (forma darajasidagi bilan birlashtiriladi) |
required | boolean | — | Majburiy holatni bekor qilish (qoidalardan avtomatik aniqlanadi) |
labelWidth | string | number | — | Forma darajasidagi yorliq kengligini bekor qilish |
showMessage | boolean | true | Ushbu maydon uchun xatolik xabarini ko'rsatish |
help | string | '' | Maydon ostidagi yordam matni |
description | string | '' | Yorliq yonidagi ma'lumot ikonkasi orqali ko'rsatiladigan tooltip matni |
dependencies | string[] | — | Ro'yxatdagi maydonlar o'zgarganda ushbu maydonni qayta tekshirish |
Events
| Event | Payload | Description |
|---|---|---|
validate | (field, valid, message) | Maydon tekshirilgandan so'ng ishga tushadi |
submit | Event | Tabiiy forma jo'natish (sukut bo'yicha oldini olinadi) |
Exposed Methods
| Method | Signature | Description |
|---|---|---|
validate | () => Promise<{ valid, errors }> | Barcha maydonlarni tekshirish |
validateFields | (fields: string[]) => Promise<{ valid, errors }> | Muayyan maydonlarni tekshirish |
resetFields | () => void | Tekshiruv holatini tiklash |
clearValidation | (fields?: string[]) => void | Xatolik xabarlarini tozalash |
isDirty | ComputedRef<boolean> | Biror maydon o'zgartirilganligi |
dirtyFields | ComputedRef<string[]> | O'zgartirilgan maydon nomlari ro'yxati |
scrollToFirstError | (field: string) => void | Muayyan maydonga aylantirish |
Slots
FormItem
| Slot | Props | Description |
|---|---|---|
default | — | Forma boshqaruvi |
label | — | Maxsus yorliq tarkibi |
label-suffix | — | Yorliq matnidan keyingi tarkib |
description | — | Boyitilgan tooltip tarkibi (description prop ni almashtiradi) |
extra | — | Kiritish ostidagi qo'shimcha tarkib |
error | { errors: string[], first: string } | Maxsus xatolik xabarini ko'rsatish |
FormRule
| Property | Type | Description |
|---|---|---|
required | boolean | Maydon qiymatga ega bo'lishi kerak |
message | string | Maxsus xatolik xabari |
trigger | 'blur' | 'change' | ('blur' | 'change')[] | Tekshiruvni qachon ishga tushirish |
min | number | Minimal uzunlik/qiymat |
max | number | Maksimal uzunlik/qiymat |
len | number | Aniq uzunlik |
pattern | RegExp | Moslashtirish uchun Regex naqsh |
type | FormRuleType | O'rnatilgan tur validatori (quyiga qarang) |
validator | (value, rule) => boolean | string | Promise | Maxsus validator funksiyasi |
whitespace | boolean | Faqat bo'sh joylarni bo'sh deb hisoblash |
enum | any[] | Qiymat shulardan biri bo'lishi kerak |
not | any | Qiymat bunga teng bo'lmasligi kerak |
same | string | Boshqa maydon qiymatiga mos kelishi kerak |
different | string | Boshqa maydon qiymatidan farq qilishi kerak |
contains | string | Ushbu substringni o'z ichiga olishi kerak |
startsWith | string | Ushbu satr bilan boshlanishi kerak |
endsWith | string | Ushbu satr bilan tugashi kerak |
Type Validators
| Type | Description |
|---|---|
string | Satr bo'lishi kerak |
number | Raqam bo'lishi kerak |
integer | Butun son bo'lishi kerak |
float | O'nlik son bo'lishi kerak |
boolean | Boolean bo'lishi kerak |
array | Massiv bo'lishi kerak |
email | Haqiqiy email manzili |
url | Haqiqiy URL |
date | Parslanishi mumkin bo'lgan sana satri |
hex | Haqiqiy hex rangi (#fff, #ff5733) |
ip | Haqiqiy IPv4 manzili |
phone | Haqiqiy telefon raqami formati |
alpha | Faqat harflar (a-z, A-Z) |
alphanumeric | Faqat harflar va raqamlar |