FilterForm
Filter form component, based on z-form encapsulation.
TIP
- If form item components support attributes like
placeholder,clearable,filterable, they will be configured by default - Form responsive default configuration is
{ xl: 6, lg: 8, md: 8, sm: 12, xs: 24 }
Basic Usage
- Pass
columnsto define the form,modelValuefor form data,optionsfor data configuration items - Events use
on+event name - Form item component attributes can be configured directly in the
columnitem FormItemcomponent attributes (form item decorator component) are configured in theformItemPropsfield. For convenience, some fields can also take effect when configured directly in thecolumnitem (such as:label,required,message, etc.)
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
onInput: (val: string) => {
console.log(val, 'input event')
},
onChange: (val: string) => {
console.log(val, 'change event')
},
},
{
component: 'select',
field: 'gender',
label: 'Gender',
onChange: (val: string) => {
console.log(val, 'change event')
},
onFocus: () => {
console.log('focus event')
},
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
onChange: (val: string) => {
console.log(val, 'change event')
},
},
]
function handleSearch() {
console.log(formData.value, 'search')
}
function handleReset() {
console.log(formData.value, 'reset')
}
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
@search="handleSearch"
@reset="handleReset"
/>
</template>Validation
- Add
requiredfield incolumnsform items, or setrequiredfield informItemPropsto set required fields. Validation messages will be automatically generated based onlabelor can be customized. - Pass
rulesfield toz-filter-formto define form validation rules. - Configure
rulesincolumnsform items to define validation rules for current form item.
<script lang="ts" setup>
import { ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const rules = {
time: [{ required: true, message: 'Date is required' }],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
required: true,
message: 'Please enter full name',
},
{
component: 'select',
field: 'gender',
formItemProps: {
required: true,
label: 'Gender',
},
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
rules: {
required: true,
message: 'Date is required',
},
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
:rules="rules"
size="small"
label-width="80px"
/>
</template>Custom Form Items
We can use slot or render to customize form item content.
Custom content also uses hide to change visibility state.
<script lang="ts" setup>
import { h, ref } from 'vue'
const formRef = ref()
const formData = ref({
name: 'Jack',
age: '',
height: 'Custom Height',
})
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
},
{
slot: 'ageSlot',
label: 'Age',
hide: () => !formData.value.name
},
{
render: () => h('span', {}, formData.value.height),
label: 'Height',
},
]
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:columns="columns"
size="small"
label-width="80px"
>
<template #ageSlot>
<el-input v-model="formData.age" placeholder="Please enter age" clearable />
</template>
</z-filter-form>
</template>Custom Label and Error
label and error support passing strings, render functions or concatenated Slot strings
<script lang="ts" setup>
import { h, ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: () => h('span', {}, 'Name'),
required: true,
error: 'error message',
},
{
component: 'select',
field: 'gender',
label: 'labelSlot',
required: true,
error: h('span', {}, 'errorSlot'),
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
required: true,
error: 'errorSlot',
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
>
<template #labelSlot>
<span>Gender</span>
</template>
<template #errorSlot>
<span>Date is required</span>
</template>
</z-filter-form>
</template>Linkage
Use hide to configure form item visibility.
TIP
If hide is configured in column, the data passed by search event will filter hidden form items (custom form items need to pass field). You can configure filterHiddenFields to false to turn it off, default is true.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
address: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
},
{
component: 'select',
field: 'gender',
label: 'Gender',
},
{
slot: 'addressSlot',
label: 'Address',
field: 'address', // 传入field字段,隐藏时过滤
hide: () => !formData.value.name
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
hide: () => !formData.value.gender,
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
function handleSearch (data: any) {
console.log(data)
}
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
@search="handleSearch"
>
<template #addressSlot>
<el-input v-model="formData.address" placeholder="Please enter address" clearable />
</template>
</z-filter-form>
</template>Operation Buttons
Button operations will have search and reset events, with built-in reset and validation operations
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
required: true,
},
{
component: 'select',
field: 'gender',
label: 'Gender',
required: true,
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
required: true,
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
function handleSearch() {
console.log(formData.value, 'formData')
}
function handleReset() {
console.log(formData.value, 'formData')
}
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
@search="handleSearch"
@reset="handleReset"
/>
</template>Set searchButtonLabel, resetButtonLabel, searchButtonLoading, resetButtonLoading to set button text and loading state.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const searchButtonLoading = ref(false)
const resetButtonLoading = ref(false)
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
required: true,
},
{
component: 'select',
field: 'gender',
label: 'Gender',
required: true,
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
required: true,
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
async function handleSearch() {
searchButtonLoading.value = true
await delay(200)
searchButtonLoading.value = false
console.log(formData.value, 'formData')
}
async function handleReset() {
resetButtonLoading.value = true
await delay(200)
resetButtonLoading.value = false
console.log(formData.value, 'formData')
}
function delay(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
search-button-label="Search"
reset-button-label="Reset"
:search-button-loading="searchButtonLoading"
:reset-button-loading="resetButtonLoading"
@search="handleSearch"
@reset="handleReset"
/>
</template>Set searchButtonProps, resetButtonProps to set button text and loading state.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const searchButtonProps = reactive({
loading: false,
label: 'Search',
type: 'primary',
})
const resetButtonProps = reactive({
loading: false,
label: 'Reset',
type: 'danger',
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
required: true,
},
{
component: 'select',
field: 'gender',
label: 'Gender',
required: true,
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
required: true,
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
async function handleSearch() {
searchButtonProps.loading = true
await delay(200)
searchButtonProps.loading = false
console.log(formData.value, 'formData')
}
async function handleReset() {
resetButtonProps.loading = true
await delay(200)
resetButtonProps.loading = false
console.log(formData.value, 'formData')
}
function delay(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
:search-button-props="searchButtonProps"
:reset-button-props="resetButtonProps"
@search="handleSearch"
@reset="handleReset"
/>
</template>Customize operation buttons through formOperation slot or render function.
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
required: true,
},
{
component: 'select',
field: 'gender',
label: 'Gender',
required: true,
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
required: true,
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
function handleSearch() {
formRef.value.validate((val: string) => {
if (val)
console.log(formData.value, 'formData')
})
}
function handleReset() {
formRef.value.resetFields()
}
function renderOperation() {
return h('span', {}, 'Search')
}
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
>
<template #formOperation>
<el-button type="primary" @click="handleSearch">
Search
</el-button>
<el-button type="warning" @click="handleReset">
Reset
</el-button>
</template>
</z-filter-form>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
:render-operation="renderOperation"
/>
</template>Default Collapsed
Configure collapsed to false, the form will be collapsed by default
<script lang="ts" setup>
import { ref } from 'vue'
const formRef = ref()
const formData = ref({
name: '',
gender: '',
time: [],
})
const options = {
gender: [
{ label: 'Male', value: '1' },
{ label: 'Female', value: '2' },
],
}
const columns = [
{
component: 'input',
field: 'name',
label: 'Name',
},
{
component: 'select',
field: 'gender',
label: 'Gender',
},
{
component: 'el-date-picker',
field: 'time',
label: 'Date',
fieldProps: {
type: 'daterange',
startPlaceholder: 'Start Date',
endPlaceholder: 'End Date',
},
},
]
</script>
<template>
<z-filter-form
ref="formRef"
v-model="formData"
:options="options"
:columns="columns"
size="small"
label-width="80px"
:collapsed="false"
/>
</template>z-filter-form Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| modelValue | Form data object | object | — |
| collapsed | Form default expand/collapse | boolean | true |
| searchButtonProps | Search button attribute configuration | object | — |
| searchButtonLabel | Search button text | string | Search |
| searchButtonLoading | Search button loading state | boolean | — |
| resetButtonProps | Reset button attribute configuration | object | — |
| resetButtonLabel | Reset button text | string | Reset |
| resetButtonLoading | Reset button loading state | boolean | — |
| rules | Form validation rules | object | — |
| label-position | Position of form field labels. When set to left or right, label-width property is also required | enum | right |
| label-width | Width of labels, e.g. '50px'. Form items that are direct children of Form will inherit this value. Can use auto. | string / number | '' |
| label-suffix | Suffix for form field labels | string | '' |
| hide-required-asterisk | Whether to hide red asterisk next to required field labels | boolean | false |
| require-asterisk-position | Position of asterisk | left / right | left |
| show-message | Whether to show validation error messages | boolean | true |
| inline-message | Whether to display validation messages inline | boolean | false |
| status-icon | Whether to display validation result feedback icons in input boxes | boolean | false |
| validate-on-rule-change | Whether to trigger validation immediately after rules property changes | boolean | true |
| size | Size for controlling components within this form | large / default / small | — |
| disabled | Whether to disable all components in this form. If set to true, it will override the disabled property of internal components | boolean | false |
| scroll-to-error | When validation fails, scroll to the first error form item | boolean | false |
| scroll-into-view-options | When validation has failed results, scroll to the first failed form item | object / boolean | — |
z-filter-form Methods
| Name | Description | Type |
|---|---|---|
| validate | Validate the entire form content. Accepts a callback function or returns Promise. | Function |
| validateField | Validate a specific field | Function |
| resetFields | Reset this form item, reset its value to initial value and remove validation result | Function |
| scrollToField | Scroll to specified field | Function |
| clearValidate | Clear validation information for a specific field | Function |
Column Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| component | Form item component | string / () => VNode | — |
| field | Field name | string | — |
| fieldProps | component component attributes | object | — |
| formItemProps | formItem component attributes | object | — |
| label | Form label name | string / () => VNode | — |
| hide | Show/hide | boolean / (formData) => boolean | — |
| show | Show/hide using v-show | boolean / (formData) => boolean | — |
| slot | Form item custom content slot | string | — |
| render | Form item custom content render | () => VNode | — |
| required | Whether form item is required | boolean | — |
| rules | Validation rules for this form item | boolean | — |
| error | Error message | string / () => VNode | — |
| tooltip | Tooltip information | string / () => VNode | — |
| extra | Extra information | string / () => VNode | — |
| children | Effective in form collapse mode, column array | array | — |
| span | Number of grid cells occupied | number | — |
| offset | Number of spacing grids on the left | number | — |
| pull | Number of grids to move left | number | — |
| push | Number of grids to move right | boolean | — |
| xs | <768px responsive grid number or grid attribute object | number / object | — |
| sm | ≥768px responsive grid number or grid attribute object | number / object | — |
| md | ≥992px responsive grid number or grid attribute object | number / object | — |
| lg | ≥1200px responsive grid number or grid attribute object | number / object | — |
| xl | ≥1920px responsive grid number or grid attribute object | number / object | — |
formItemProps Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
| tooltip | Tooltip text | string / () => VNode | — |
| extra | Extra information | string / () => VNode | — |
| colon | Colon | boolean | — |
| label | Label text | string / () => VNode | — |
| label-width | Label width, e.g. '50px'. Can use auto. | string / number | '' |
| required | Whether it's a required field. If not set, it will be determined based on validation rules | boolean | — |
| rules | Form validation rules. For specific configuration see table below, more content can refer to async-validator | object | — |
| error | Error message when form field validation fails. Setting this value will cause form validation status to become error and display this error message. | string / () => VNode | — |
| show-message | Whether to show validation error messages | boolean | true |
| inline-message | Whether to display validation messages inline | string / boolean | '' |
| size | Default size for controlling components under this form field | large / default / small | — |
| for | Same capability as native label | string | — |
| validate-status | Validation status of formItem | error / validating / success | — |