Skip to content

el-form

测试1
测试2
测试222
测试3
测试4
测试5
To
测试6
Select
测试7
slot
render
测试8
Select
vue
<script  setup>
import BaseForm from '@/components/BaseForm.vue';
import { ElButton } from 'element-plus'
import formConfig from './formConfig.jsx'
import { ref } from 'vue'
const formRef = ref(null)
const formData = ref({
  test1: '',
  test2: 15,
  test3: '',
  test4: [],
  test5: [],
  test6: '',
  test7: '',
  test8: '',
  tests: ''
})

const add = async () => {
  try {
    await formRef.value.validate()
    console.log('校验成功')
  } catch (error) {
    console.log('校验失败')
  }
}
const reset = () => {
  formRef.value.resetFields()
}
const confim = () => {
  console.log(formData.value)
}

</script>

<template>
    <BaseForm
        label-width="90px"
        label-position="right"
        ref="formRef"
        v-model="formData"
        v-bind="formConfig"
        @validate="confim"
    >
        <template #tests>
        <el-button>ee</el-button>
        </template>
    </BaseForm>
    <el-button @click="add">
        提交
    </el-button>
    <el-button @click="reset">
        重置
    </el-button>
</template>
<script  setup>
import BaseForm from '@/components/BaseForm.vue';
import { ElButton } from 'element-plus'
import formConfig from './formConfig.jsx'
import { ref } from 'vue'
const formRef = ref(null)
const formData = ref({
  test1: '',
  test2: 15,
  test3: '',
  test4: [],
  test5: [],
  test6: '',
  test7: '',
  test8: '',
  tests: ''
})

const add = async () => {
  try {
    await formRef.value.validate()
    console.log('校验成功')
  } catch (error) {
    console.log('校验失败')
  }
}
const reset = () => {
  formRef.value.resetFields()
}
const confim = () => {
  console.log(formData.value)
}

</script>

<template>
    <BaseForm
        label-width="90px"
        label-position="right"
        ref="formRef"
        v-model="formData"
        v-bind="formConfig"
        @validate="confim"
    >
        <template #tests>
        <el-button>ee</el-button>
        </template>
    </BaseForm>
    <el-button @click="add">
        提交
    </el-button>
    <el-button @click="reset">
        重置
    </el-button>
</template>
js
import { ElButton } from 'element-plus'
const formConfig = {
  formList: [
    {
      type: 'input',
      prop: 'test1',
      label: '测试1',
      rules: [
        {
          required: true,
          message: 'Please select Activity count',
          trigger: 'blur'
        }
      ],
      col: {
        span: 12
      }
    },
    {
      type: 'slider',
      prop: 'test2',
      label: '测试2',
      col: {
        span: 12
      }
    },
    {
      type: 'slider',
      prop: 'test222',
      label: '测试222',
      col: {
        span: 12
      }
    },
    {
      type: 'radio',
      props: {
        data: [
          {
            value: '1',
            label: '11'
          },
          {
            value: '2',
            label: '22'
          }
        ]
      },
      prop: 'test3',
      label: '测试3',
      col: {
        span: 12
      }
    },
    {
      type: 'checkbox',
      props: {
        data: [
          {
            value: '1',
            label: '11'
          },
          {
            value: '2',
            label: '22'
          }
        ]
      },
      prop: 'test4',
      label: '测试4'
    },
    {
      type: 'date',
      dateType: 'daterange',
      prop: 'test5',
      label: '测试5',
      props: {
        'start-placeholder': 'Start date',
        'end-placeholder': 'End date',
        'range-separator': 'To'
      },
      col: {
        span: 12
      }
    },
    {
      type: 'time',
      prop: 'test6',
      label: '测试6'
    },
    {
      type: 'switch',
      prop: 'test7',
      label: '测试7'
    },
    {
      type: 'slot',
      prop: 'tests',
      label: 'slot'
    },
    {
      type: 'render',
      render: () => {
        return (
        <ElButton>render</ElButton>
        )
      },
      label: 'render'
    },
    {
      type: 'select',
      prop: 'test8',
      label: '测试8',
      props: {
        data: [
          {
            value: '1',
            label: '11'
          },
          {
            value: '2',
            label: '22'
          }
        ]
      }
    }
  ]

}
export default formConfig
import { ElButton } from 'element-plus'
const formConfig = {
  formList: [
    {
      type: 'input',
      prop: 'test1',
      label: '测试1',
      rules: [
        {
          required: true,
          message: 'Please select Activity count',
          trigger: 'blur'
        }
      ],
      col: {
        span: 12
      }
    },
    {
      type: 'slider',
      prop: 'test2',
      label: '测试2',
      col: {
        span: 12
      }
    },
    {
      type: 'slider',
      prop: 'test222',
      label: '测试222',
      col: {
        span: 12
      }
    },
    {
      type: 'radio',
      props: {
        data: [
          {
            value: '1',
            label: '11'
          },
          {
            value: '2',
            label: '22'
          }
        ]
      },
      prop: 'test3',
      label: '测试3',
      col: {
        span: 12
      }
    },
    {
      type: 'checkbox',
      props: {
        data: [
          {
            value: '1',
            label: '11'
          },
          {
            value: '2',
            label: '22'
          }
        ]
      },
      prop: 'test4',
      label: '测试4'
    },
    {
      type: 'date',
      dateType: 'daterange',
      prop: 'test5',
      label: '测试5',
      props: {
        'start-placeholder': 'Start date',
        'end-placeholder': 'End date',
        'range-separator': 'To'
      },
      col: {
        span: 12
      }
    },
    {
      type: 'time',
      prop: 'test6',
      label: '测试6'
    },
    {
      type: 'switch',
      prop: 'test7',
      label: '测试7'
    },
    {
      type: 'slot',
      prop: 'tests',
      label: 'slot'
    },
    {
      type: 'render',
      render: () => {
        return (
        <ElButton>render</ElButton>
        )
      },
      label: 'render'
    },
    {
      type: 'select',
      prop: 'test8',
      label: '测试8',
      props: {
        data: [
          {
            value: '1',
            label: '11'
          },
          {
            value: '2',
            label: '22'
          }
        ]
      }
    }
  ]

}
export default formConfig

基本使用

功能介绍

使用JSON形式构建表单,传入 formList 数组。 内部支持el-inputel-sliderel-radioel-checkboxel-date-pickerel-time-selectel-switchel-selectslot

一般配置

通过 type 选择组件名称,可选 input,slider,radio,checkbox,date,time,switch,select,通过 prop 设置字段名,通过 label 设置显示的名称。

js
{
  type: 'input',
  prop: 'test1',
  label: '测试1',
}
{
  type: 'input',
  prop: 'test1',
  label: '测试1',
}

表单校验

通过 rules 属性传入,使用方式跟element原始使用方式一样,支持数组或对象

js
{
  type: 'input',
  prop: 'test1',
  label: '测试1',  
  rules: [
    {
      required: true,
      message: 'Please select Activity count',
      trigger: 'blur'
    }
  ],
}
{
  type: 'input',
  prop: 'test1',
  label: '测试1',  
  rules: [
    {
      required: true,
      message: 'Please select Activity count',
      trigger: 'blur'
    }
  ],
}

控制表单子项的长短

通过 col 属性设置,使用方式跟 el-col 一样,总长度为24,12则表示一般宽度

js
{
  col: {
    span: 12
  }
}
{
  col: {
    span: 12
  }
}

对子组件的参数透

使用 props 进行透传,需要注意的是要修改el-radio-groupel-checkbox-group 的属性通过字段 groupProps 传入修改。有列表数据的组件统一使用 data 字段传入需要的数据数组,比如 radioselect 组件

js
{
  type: 'radio',
  props: {
    data: [
      {
        value: '1',
        label: '11'
      },
      {
        value: '2',
        label: '22'
      }
    ]
  },
},
{
  type: 'date',
  props: {
    'start-placeholder': 'Start date',
    'end-placeholder': 'End date',
    'range-separator': 'To'
  }
}
{
  type: 'radio',
  props: {
    data: [
      {
        value: '1',
        label: '11'
      },
      {
        value: '2',
        label: '22'
      }
    ]
  },
},
{
  type: 'date',
  props: {
    'start-placeholder': 'Start date',
    'end-placeholder': 'End date',
    'range-separator': 'To'
  }
}

使用render渲染

会返回 { item, formData, formList } 这些数据给内部使用

js
{
  type: 'render',
  render: ({item ,formData,formList}) => {
    return (
    <ElButton>render</ElButton>
    )
  },
  label: 'render'
}
{
  type: 'render',
  render: ({item ,formData,formList}) => {
    return (
    <ElButton>render</ElButton>
    )
  },
  label: 'render'
}

:::

事件

组件内部导出三个事件,validate 用于校验,clearValidate 用于清除校验,resetFields 用于重置表单,通过组件的ref获取这些事件

js
formRef.value.validate()
formRef.value.validate()

组件代码

vue
<template>
  <div class="base-form">
    <el-form
      :model="formData"
      :rules="rules"
      ref="formRef"
      v-bind="$attrs"
    >
      <el-row v-bind="row">
        <el-col
          v-for="item in formList"
          :key="item.prop"
          v-bind="item.col"
        >
          <el-form-item
            :label="item.label"
            :prop="item.prop"
            v-bind="item"
          >
            <!-- 输入框 -->
            <el-input
              v-if="item.type === 'input'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 滑块 -->
            <el-slider
              v-if="item.type === 'slider'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 单选 -->
            <el-radio-group
              v-if="item.type === 'radio'"
              v-model="formData[item.prop]"
              v-bind="item.groupProps"
            >
              <template
                v-for="ra in item.props?.data || []"
                :key="ra.value"
              >
                <el-radio-button
                  v-if="item.radioType==='radio-button'"
                  :label="ra.value"
                  v-bind="item.props"
                >
                  {{ ra.label }}
                </el-radio-button>
                <el-radio
                  v-else
                  :label="ra.value"
                  v-bind="item.props"
                >
                  {{ ra.label }}
                </el-radio>
              </template>
            </el-radio-group>
            <!-- 复选框 -->
            <el-checkbox-group
              v-if="item.type === 'checkbox'"
              v-model="formData[item.prop]"
              v-bind="item.groupProps"
            >
              <el-checkbox
                v-for="ch in item.props?.data || []"
                :label="ch.value"
                :key="ch.value"
                v-bind="item.props"
              >
                {{ ch.label }}
              </el-checkbox>
            </el-checkbox-group>
            <!-- 日期  日期时间 起止时间 -->
            <el-date-picker
              v-if="item.type === 'date'"
              :type="item.dateType || 'date'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 时间 -->
            <el-time-select
              v-if="item.type === 'time'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 开关 -->
            <el-switch
              v-if="item.type === 'switch'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 下拉框 -->
            <el-select
              v-if="item.type === 'select'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            >
              <el-option
                v-for="op in item.props?.data || []"
                :label="op.label"
                :value="op.value"
                :key="op.value"
              >
                {{ op.label }}
              </el-option>
            </el-select>
            <template v-if="item.type==='slot'">
              <slot
                :name="item.prop"
                v-bind="{ item, formData, formList }"
              />
            </template>
            <template v-if="item.type==='render'">
              <component
                :is="item.render"
                v-bind="{ item, formData, formList }"
              />
            </template>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
const prop = defineProps({
  formList: {
    type: Array,
    default: () => ([])
  },
  row: {
    type: Object
  },
  modelValue: {
    type: Object,
    default: () => ({})
  }
})
const emit = defineEmits(['validate', 'update:modelValue'])

const formData = ref({})
watch(() => prop.modelValue, (newValue) => {
  formData.value = newValue
}, { immediate: true })

watch(formData, (newValue) => {
  emit('update:modelValue', newValue)
})

const rules = computed(() => {
  const rules = prop.formList.reduce((map, i) => {
    if (i.rules) {
      map[i.prop] = i.rules
    }
    return map
  }, {})
  return rules
})

const formRef = ref(null)
// 验证表单

const validate = () => {
  return formRef.value.validate()
}
// 重置表单
const resetFields = () => {
  formRef.value.resetFields()
}
// 重置验证结果
const clearValidate = () => {
  formRef.value.clearValidate()
}
defineExpose({
  validate,
  clearValidate,
  resetFields
})
</script>

<style lang="scss" scoped>

</style>
<template>
  <div class="base-form">
    <el-form
      :model="formData"
      :rules="rules"
      ref="formRef"
      v-bind="$attrs"
    >
      <el-row v-bind="row">
        <el-col
          v-for="item in formList"
          :key="item.prop"
          v-bind="item.col"
        >
          <el-form-item
            :label="item.label"
            :prop="item.prop"
            v-bind="item"
          >
            <!-- 输入框 -->
            <el-input
              v-if="item.type === 'input'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 滑块 -->
            <el-slider
              v-if="item.type === 'slider'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 单选 -->
            <el-radio-group
              v-if="item.type === 'radio'"
              v-model="formData[item.prop]"
              v-bind="item.groupProps"
            >
              <template
                v-for="ra in item.props?.data || []"
                :key="ra.value"
              >
                <el-radio-button
                  v-if="item.radioType==='radio-button'"
                  :label="ra.value"
                  v-bind="item.props"
                >
                  {{ ra.label }}
                </el-radio-button>
                <el-radio
                  v-else
                  :label="ra.value"
                  v-bind="item.props"
                >
                  {{ ra.label }}
                </el-radio>
              </template>
            </el-radio-group>
            <!-- 复选框 -->
            <el-checkbox-group
              v-if="item.type === 'checkbox'"
              v-model="formData[item.prop]"
              v-bind="item.groupProps"
            >
              <el-checkbox
                v-for="ch in item.props?.data || []"
                :label="ch.value"
                :key="ch.value"
                v-bind="item.props"
              >
                {{ ch.label }}
              </el-checkbox>
            </el-checkbox-group>
            <!-- 日期  日期时间 起止时间 -->
            <el-date-picker
              v-if="item.type === 'date'"
              :type="item.dateType || 'date'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 时间 -->
            <el-time-select
              v-if="item.type === 'time'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 开关 -->
            <el-switch
              v-if="item.type === 'switch'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            />
            <!-- 下拉框 -->
            <el-select
              v-if="item.type === 'select'"
              v-model="formData[item.prop]"
              v-bind="item.props"
            >
              <el-option
                v-for="op in item.props?.data || []"
                :label="op.label"
                :value="op.value"
                :key="op.value"
              >
                {{ op.label }}
              </el-option>
            </el-select>
            <template v-if="item.type==='slot'">
              <slot
                :name="item.prop"
                v-bind="{ item, formData, formList }"
              />
            </template>
            <template v-if="item.type==='render'">
              <component
                :is="item.render"
                v-bind="{ item, formData, formList }"
              />
            </template>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
const prop = defineProps({
  formList: {
    type: Array,
    default: () => ([])
  },
  row: {
    type: Object
  },
  modelValue: {
    type: Object,
    default: () => ({})
  }
})
const emit = defineEmits(['validate', 'update:modelValue'])

const formData = ref({})
watch(() => prop.modelValue, (newValue) => {
  formData.value = newValue
}, { immediate: true })

watch(formData, (newValue) => {
  emit('update:modelValue', newValue)
})

const rules = computed(() => {
  const rules = prop.formList.reduce((map, i) => {
    if (i.rules) {
      map[i.prop] = i.rules
    }
    return map
  }, {})
  return rules
})

const formRef = ref(null)
// 验证表单

const validate = () => {
  return formRef.value.validate()
}
// 重置表单
const resetFields = () => {
  formRef.value.resetFields()
}
// 重置验证结果
const clearValidate = () => {
  formRef.value.clearValidate()
}
defineExpose({
  validate,
  clearValidate,
  resetFields
})
</script>

<style lang="scss" scoped>

</style>
AI助手