element plus自定义表单项触发表单验证

2,777 阅读2分钟

element plus如何创建自定义表单项呢?

一直有个疑问,为什么官方文档中,就没有自定义表单项的内容呢?从element uielement plus貌似都没有,是官方就认定我们不需要自定义表单项,还是说他们觉得官方提供的组件本身已经完备到,不需要进行任何自定义的程度?

目标

  • 能自定义表单项
  • 表单进行验证时,自定义表单项也能被验证
  • 自定义表单项的bulr,focus之类事件触发时,也要能触发表单项的验证

自定义表单项组件: MyEleComp.vue

<!--
自定义表单项组件
-->
<script lang='ts' setup>
import { inject } from 'vue'
// eslint-disable-next-line
import { elFormItemKey, elFormKey } from 'element-plus'

// v-model相关定义, 用于接收外部和内部修改值再告知外部
defineProps<{
  modelValue: string
}>()
// eslint-disable-next-line
const emits = defineEmits({
  'update:modelValue': (val: string) => true
})

// 获取element plus表单项的provide, 作用是用来触发表单项的验证
const elFormItem = inject(elFormItemKey, undefined)
// const elForm = inject(elFormKey, undefined)
console.log('>>>>>>>>>>>>>> elFormItem', elFormItem)

// console.log('>>>>>>>>>>>>>> elForm', elForm)

function onBlur() {
  console.log('elFormItem', elFormItem)
  // 手动触发表单项验证
  elFormItem?.validate('blur')
}

function onChange(val: Event) {
  const inputEle: HTMLInputElement = val.target as HTMLInputElement
  console.log(inputEle.value, 'inputEle.value')
  // 告知外部, 这个表单项的值已经改变了
  emits('update:modelValue', inputEle.value)
}
</script>

<template>
  <input @blur='onBlur' @change='onChange' type='text' :value='modelValue'>
</template>

<style lang='scss' scoped>

</style>

在表单中使用自定义表单项组件

<script lang='ts' setup>
import {
  ElForm,
  ElFormItem,
  ElRadioGroup,
  ElRadio,
  ElInput,
  ElCheckboxGroup,
  ElTimePicker,
  ElSwitch,
  ElSelect,
  ElOption,
  ElDatePicker,
  ElButton,
  ElCheckbox,
  ElCol
} from 'element-plus'
import { reactive, ref } from 'vue'
import MyEleComp from './MyEleComp.vue'

const ruleForm = reactive({
  x: 'xml'
})

const rules = reactive({
  x: [
    {
      required: true,
      message: '请输入x',
      trigger: 'blur'
    }
  ]
})

const ruleFormRef = ref<any>()

function submitForm() {
  ruleFormRef.value.validate((valid: boolean) => {
    if (valid) {
      alert('submit!')
    } else {
      console.log('error submit!!')
      return false
    }
  })
}

function resetForm() {
  ruleFormRef.value.resetFields()
}
</script>

<template>

  <el-form
    ref='ruleFormRef'
    :model='ruleForm'
    :rules='rules'
    label-width='120px'
    class='demo-ruleForm'
  >
    <el-form-item label='你好' prop='x'>
      <!-- 这里引入的就是自定义表单项 -->
      <MyEleComp v-model='ruleForm.x'></MyEleComp>
    </el-form-item>
    <el-form-item>
      <el-button type='primary' @click='submitForm()'>提交</el-button>
      <el-button @click="resetForm('ruleForm')">重置</el-button>
    </el-form-item>
  </el-form>
</template>

新版本Element Plus自定义表单项触发表单验证的方式

import { useFormItem } from 'element-plus';

const { formItem } = useFormItem();

formItem?.validate('blur'); // 触发校验

如果你使用了vite-plugin-style-import组件,来自动引入element-plus的样式,那么此时还得让该组件排除引入useFormItem的样式,因为这个是不存在样式的

// 解决类Message组件样式无法自动引入问题
      createStyleImportPlugin({
        resolves: [ElementPlusResolve()],
        libs: [
          {
            // importTest 的正则表达式表示,凡属单独引入 element-plus 的 import 语句,只要不包含 useFormItem , 则自动引入 css
            importTest: /^(?!.*useFormItem).*/,
            libraryName: 'element-plus',
            esModule: true,
            resolveStyle: (name: string) => {
              return `element-plus/theme-chalk/${name}.css`
            },
          },
        ],
      })