Skip to content

FilterForm ​

Filter form component, based on z-form encapsulation.

TIP

  1. If form item components support attributes like placeholder, clearable, filterable, they will be configured by default
  2. Form responsive default configuration is { xl: 6, lg: 8, md: 8, sm: 12, xs: 24 }

Basic Usage ​

  • Pass columns to define the form, modelValue for form data, options for data configuration items
  • Events use on + event name
  • Form item component attributes can be configured directly in the column item
  • FormItem component attributes (form item decorator component) are configured in the formItemProps field. For convenience, some fields can also take effect when configured directly in the column item (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 required field in columns form items, or set required field in formItemProps to set required fields. Validation messages will be automatically generated based on label or can be customized.
  • Pass rules field to z-filter-form to define form validation rules.
  • Configure rules in columns form 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 ​

AttributeDescriptionTypeDefault
modelValueForm data objectobject—
collapsedForm default expand/collapsebooleantrue
searchButtonPropsSearch button attribute configurationobject—
searchButtonLabelSearch button textstringSearch
searchButtonLoadingSearch button loading stateboolean—
resetButtonPropsReset button attribute configurationobject—
resetButtonLabelReset button textstringReset
resetButtonLoadingReset button loading stateboolean—
rulesForm validation rulesobject—
label-positionPosition of form field labels. When set to left or right, label-width property is also requiredenumright
label-widthWidth of labels, e.g. '50px'. Form items that are direct children of Form will inherit this value. Can use auto.string / number''
label-suffixSuffix for form field labelsstring''
hide-required-asteriskWhether to hide red asterisk next to required field labelsbooleanfalse
require-asterisk-positionPosition of asteriskleft / rightleft
show-messageWhether to show validation error messagesbooleantrue
inline-messageWhether to display validation messages inlinebooleanfalse
status-iconWhether to display validation result feedback icons in input boxesbooleanfalse
validate-on-rule-changeWhether to trigger validation immediately after rules property changesbooleantrue
sizeSize for controlling components within this formlarge / default / small—
disabledWhether to disable all components in this form. If set to true, it will override the disabled property of internal componentsbooleanfalse
scroll-to-errorWhen validation fails, scroll to the first error form itembooleanfalse
scroll-into-view-optionsWhen validation has failed results, scroll to the first failed form itemobject / boolean—

z-filter-form Methods ​

NameDescriptionType
validateValidate the entire form content. Accepts a callback function or returns Promise.Function
validateFieldValidate a specific fieldFunction
resetFieldsReset this form item, reset its value to initial value and remove validation resultFunction
scrollToFieldScroll to specified fieldFunction
clearValidateClear validation information for a specific fieldFunction

Column Attributes ​

AttributeDescriptionTypeDefault
componentForm item componentstring / () => VNode—
fieldField namestring—
fieldPropscomponent component attributesobject—
formItemPropsformItem component attributesobject—
labelForm label namestring / () => VNode—
hideShow/hideboolean / (formData) => boolean—
showShow/hide using v-showboolean / (formData) => boolean—
slotForm item custom content slotstring—
renderForm item custom content render() => VNode—
requiredWhether form item is requiredboolean—
rulesValidation rules for this form itemboolean—
errorError messagestring / () => VNode—
tooltipTooltip informationstring / () => VNode—
extraExtra informationstring / () => VNode—
childrenEffective in form collapse mode, column arrayarray—
spanNumber of grid cells occupiednumber—
offsetNumber of spacing grids on the leftnumber—
pullNumber of grids to move leftnumber—
pushNumber of grids to move rightboolean—
xs<768px responsive grid number or grid attribute objectnumber / object—
sm≥768px responsive grid number or grid attribute objectnumber / object—
md≥992px responsive grid number or grid attribute objectnumber / object—
lg≥1200px responsive grid number or grid attribute objectnumber / object—
xl≥1920px responsive grid number or grid attribute objectnumber / object—

formItemProps Attributes ​

AttributeDescriptionTypeDefault
tooltipTooltip textstring / () => VNode—
extraExtra informationstring / () => VNode—
colonColonboolean—
labelLabel textstring / () => VNode—
label-widthLabel width, e.g. '50px'. Can use auto.string / number''
requiredWhether it's a required field. If not set, it will be determined based on validation rulesboolean—
rulesForm validation rules. For specific configuration see table below, more content can refer to async-validatorobject—
errorError 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-messageWhether to show validation error messagesbooleantrue
inline-messageWhether to display validation messages inlinestring / boolean''
sizeDefault size for controlling components under this form fieldlarge / default / small—
forSame capability as native labelstring—
validate-statusValidation status of formItemerror / validating / success—

Released under the MIT License.