Form
Form consists of input, select, radio, checkbox and other controls, for collecting, validating, and submitting data.
| Name | Category | Description | Type | Default |
|---|---|---|---|---|
inline | Style | Whether to use inline form layout | boolean | false |
labelWidth | Style | Label width | number | string | — |
labelPosition | Style | Label position | 'left' | 'right' | 'top' | 'right' |
hideRequiredAsterisk | Style | Whether to hide red asterisk | boolean | false |
requiredAsteriskPosition | Style | Asterisk position | 'left' | 'right' | 'left' |
FormItemlabelWidth | Style | Label width | number | string | — |
disabled | State | Whether to disable form | boolean | false |
FormItemdisabled | State | Whether disabled | boolean | false |
rules | Behavior | Form validation rules (supports Zod schema) | FormRules | — |
statusIcon | Behavior | Whether to show status icon after validation | boolean | false |
showMessage | Behavior | Whether to show validation error message | boolean | true |
FormItemrequired | Behavior | Whether required | boolean | false |
FormItemrules | Behavior | Validation rules (supports Zod schema or required shorthand) | FormItemRule[] | — |
FormItemshowMessage | Behavior | Whether to show validation error | boolean | true |
FormItemfor | Behavior | Label's for attribute, associates with a specific form control | string | — |
model | Content | Form data object | Record<string, any> | — |
labelSuffix | Content | Label suffix | string | — |
FormItemprop | Content | Key name of model | string | string[] | — |
FormItemlabel | Content | Label text | string | — |
FormItemerror | Content | Error message | string | — |
validate | Event | Triggered after field validation | (prop: string, isValid: boolean, message: string) => void | — |
FormItemdefault | Slot | Form item content | — | |
FormItemlabel | Slot | Custom label | — | |
FormItemerror | Slot | Custom error message | — | |
validate | Expose | Validate the whole form | (callback?: FormValidateCallback) => Promise<boolean> | — |
validateField | Expose | Validate specific fields | (props?: string[], callback?: FormValidateCallback) => Promise<boolean> | — |
resetFields | Expose | Reset form fields | (props?: string[]) => void | — |
clearValidate | Expose | Clear validation status | (props?: string[]) => void | — |
Basic Usage
Basic form data control, including various form items.
<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>Form Validation
Form validation uses Zod schemas. Each rule can provide a schema (Zod type) or use the required shorthand for simple required checks.
<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 Form
Set inline to display form items in a horizontal row, useful for search forms and filters.
<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
You can change the position of form field labels by setting label-position attribute.
<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
Set status-icon to show check/close icons after field validation.
<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
Set disabled on the form to disable all form controls.
<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>