Form 表单
由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据。
| 名称 | 分类 | 说明 | 类型 | 默认值 |
|---|---|---|---|---|
inline | 风格 | 是否使用行内表单 | boolean | false |
labelWidth | 风格 | 标签宽度 | number | string | — |
labelPosition | 风格 | 标签位置 | 'left' | 'right' | 'top' | 'right' |
hideRequiredAsterisk | 风格 | 是否隐藏必填字段的标签旁边的红色星号 | boolean | false |
requiredAsteriskPosition | 风格 | 星号位置 | 'left' | 'right' | 'left' |
FormItemlabelWidth | 风格 | 标签宽度 | number | string | — |
disabled | 状态 | 是否禁用表单 | boolean | false |
FormItemdisabled | 状态 | 是否禁用 | boolean | false |
rules | 行为 | 表单验证规则(支持 Zod schema) | FormRules | — |
statusIcon | 行为 | 验证后是否显示状态图标 | boolean | false |
showMessage | 行为 | 是否显示校验错误信息 | boolean | true |
FormItemrequired | 行为 | 是否必填 | boolean | false |
FormItemrules | 行为 | 验证规则(支持 Zod schema 或 required 简写) | FormItemRule[] | — |
FormItemshowMessage | 行为 | 是否显示校验错误信息 | boolean | true |
FormItemfor | 行为 | 标签的 for 属性,关联到指定的表单控件 | string | — |
model | 内容 | 表单数据对象 | Record<string, any> | — |
labelSuffix | 内容 | 标签后缀 | string | — |
FormItemprop | 内容 | model 的键名 | string | string[] | — |
FormItemlabel | 内容 | 标签文本 | string | — |
FormItemerror | 内容 | 错误信息 | string | — |
validate | 事件 | 字段验证后触发 | (prop: string, isValid: boolean, message: string) => void | — |
FormItemdefault | 插槽 | 表单项内容 | — | |
FormItemlabel | 插槽 | 自定义标签 | — | |
FormItemerror | 插槽 | 自定义错误信息 | — | |
validate | 暴露 | 验证整个表单 | (callback?: FormValidateCallback) => Promise<boolean> | — |
validateField | 暴露 | 验证指定字段 | (props?: string[], callback?: FormValidateCallback) => Promise<boolean> | — |
resetFields | 暴露 | 重置表单字段 | (props?: string[]) => void | — |
clearValidate | 暴露 | 清除验证状态 | (props?: string[]) => void | — |
基础用法
基本的表单数据域控制,包含各种表单项。
<template>
<px-form :model="form" label-width="80px">
<px-form-item label="Name">
<px-input v-model="form.name" placeholder="Enter name" />
</px-form-item>
<px-form-item label="Email">
<px-input v-model="form.email" placeholder="Enter email" />
</px-form-item>
<px-form-item label="Active">
<px-switch v-model="form.active" />
</px-form-item>
<px-form-item>
<px-button type="primary" @click="onSubmit">Submit</px-button>
<px-button @click="onReset">Reset</px-button>
</px-form-item>
</px-form>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
import { reactive } from 'vue';
const form = reactive({
name: '',
email: '',
active: false,
});
const onSubmit = () => {
PxMessage.success('Submit!');
};
const onReset = () => {
form.name = '';
form.email = '';
form.active = false;
};
</script>表单校验
表单校验使用 Zod 模式验证。每条规则可提供 schema(Zod 类型)或使用 required 简写进行简单的必填检查。
<template>
<px-form ref="formRef" :model="form" :rules="rules" label-width="80px">
<px-form-item label="Name" prop="name">
<px-input v-model="form.name" placeholder="Enter name" />
</px-form-item>
<px-form-item label="Email" prop="email">
<px-input v-model="form.email" placeholder="Enter email" />
</px-form-item>
<px-form-item>
<px-button type="primary" @click="onSubmit">Submit</px-button>
<px-button @click="onReset">Reset</px-button>
</px-form-item>
</px-form>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
import { reactive, ref } from 'vue';
import { z } from 'zod';
const formRef = ref();
const form = reactive({
name: '',
email: '',
});
const rules = {
name: [
{ schema: z.string().min(1, 'Please input name'), trigger: 'blur' },
{ schema: z.string().min(2).max(20, 'Length should be 2 to 20'), trigger: 'blur' },
],
email: [
{ schema: z.string().min(1, 'Please input email'), trigger: 'blur' },
{ schema: z.string().email('Please input a valid email'), trigger: 'blur' },
],
};
const onSubmit = async () => {
try {
await formRef.value.validate();
PxMessage.success('Submit success!');
} catch {
PxMessage.danger('Validation failed');
}
};
const onReset = () => {
formRef.value.resetFields();
};
</script>行内表单
设置 inline 属性可以让表单项水平排列,适用于搜索表单和筛选器。
<template>
<px-form ref="formRef" :model="form" inline label-width="60px">
<px-form-item label="Name" prop="name">
<px-input v-model="form.name" placeholder="Name" />
</px-form-item>
<px-form-item label="Email" prop="email">
<px-input v-model="form.email" placeholder="Email" />
</px-form-item>
<px-form-item>
<px-button type="primary" @click="onSearch">Search</px-button>
</px-form-item>
</px-form>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
import { reactive, ref } from 'vue';
const formRef = ref();
const form = reactive({
name: '',
email: '',
});
const onSearch = () => {
PxMessage.success('Search submitted!');
};
</script>标签位置
通过设置 label-position 属性可以改变表单域标签的位置。
<template>
<div class="demo-form">
<div class="buttons">
<px-button @click="labelPosition = 'left'">Left</px-button>
<px-button @click="labelPosition = 'right'">Right</px-button>
<px-button @click="labelPosition = 'top'">Top</px-button>
</div>
<px-form :model="form" :label-position="labelPosition" label-width="80px">
<px-form-item label="Name">
<px-input v-model="form.name" placeholder="Enter name" />
</px-form-item>
<px-form-item label="Email">
<px-input v-model="form.email" placeholder="Enter email" />
</px-form-item>
<px-form-item>
<px-button type="primary" @click="onSubmit">Submit</px-button>
<px-button @click="onCancel">Cancel</px-button>
</px-form-item>
</px-form>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const labelPosition = ref<'left' | 'right' | 'top'>('right');
const form = reactive({
name: '',
email: '',
});
function onSubmit() {}
function onCancel() {
form.name = '';
form.email = '';
}
</script>
<style scoped>
.demo-form .buttons {
margin-bottom: 16px;
display: flex;
gap: 8px;
}
</style>状态图标
设置 status-icon 属性可以在验证后显示成功/失败图标。
<template>
<px-form ref="formRef" :model="form" :rules="rules" status-icon label-width="80px">
<px-form-item label="Name" prop="name">
<px-input v-model="form.name" placeholder="Enter name" />
</px-form-item>
<px-form-item label="Email" prop="email">
<px-input v-model="form.email" placeholder="Enter email" />
</px-form-item>
<px-form-item>
<px-button type="primary" @click="onSubmit">Validate</px-button>
<px-button @click="onReset">Reset</px-button>
</px-form-item>
</px-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { z } from 'zod';
const formRef = ref();
const form = reactive({
name: '',
email: '',
});
const rules = {
name: [{ schema: z.string().min(1, 'Name is required'), trigger: 'blur' }],
email: [{ schema: z.string().email('Invalid email'), trigger: 'blur' }],
};
const onSubmit = async () => {
try {
await formRef.value.validate();
} catch {
// validation failed
}
};
const onReset = () => {
formRef.value.resetFields();
};
</script>禁用
在表单上设置 disabled 属性可以禁用所有表单控件。
<template>
<px-form :model="form" disabled label-width="80px">
<px-form-item label="Name" prop="name">
<px-input v-model="form.name" placeholder="Enter name" />
</px-form-item>
<px-form-item label="Email" prop="email">
<px-input v-model="form.email" placeholder="Enter email" />
</px-form-item>
<px-form-item label="Active" prop="active">
<px-switch v-model="form.active" />
</px-form-item>
<px-form-item>
<px-button type="primary" disabled>Submit</px-button>
</px-form-item>
</px-form>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const form = reactive({
name: 'Sakana',
email: 'sakana@example.com',
active: true,
});
</script>