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.