Skip to content

CollapseForm 折叠表单

基于ZForm组件和ElCollapse组件封装。

常规使用

表单类型type传入collapsecolumn项中配置children(表单项),可以实现可折叠表单。

activeCollapse绑定展开的折叠项label,如不想绑定label,请在column项中配置字段key

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'

const activeCollapse = ref(['文本', '标题'])
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

const options = {
  gender: [
    { label: '男', value: '1' },
    { label: '女', value: '2' },
  ],
}

const columns = [
  {
    label: '文本',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: '姓名',
        onInput: (val: string) => {
          console.log(val, 'input event')
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        rules: {
          required: true,
        },
      },
    ],
  },
  {
    label: '标题',
    children: [
      {
        component: 'select',
        field: 'gender',
        label: '性别',
        md: 12,
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        onFocus: () => {
          console.log('focus event')
        },
      },
      {
        component: 'el-date-picker',
        field: 'time',
        label: '出生日期',
        md: 12,
        fieldProps: {
          type: 'daterange',
          startPlaceholder: '开始日期',
          endPlaceholder: '结束日期',
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
      },
    ],
  },
  {
    slot: 'operate',
  },
]

function reset() {
  formRef.value.resetFields()
}

function submit() {
  formRef.value.validate((valid: boolean) => {
    if (valid) {
      ElMessage.success('成功')
      console.log(formData.value, 'config.formData')
    }
    else {
      console.log('error submit!!')
      return false
    }
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeCollapse="activeCollapse"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="collapse"
  >
    <template #operate>
      <div class="mt-4 w-full flex">
        <el-button class="w-full" @click="reset">
          重置
        </el-button>
        <el-button class="w-full" type="primary" @click="submit">
          提交
        </el-button>
      </div>
    </template>
  </z-form>
</template>

标题

默认column项的label字段为折叠项的name,如果label为函数或不想将label作为折叠项name,请额外传入key字段。支持slot插槽自定义标题。

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
import { ElMessage } from 'element-plus'

const activeCollapse = ref(['bbb', 'labelSlot'])
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

const options = {
  gender: [
    { label: '男', value: '1' },
    { label: '女', value: '2' },
  ],
}

const columns = [
  {
    label: () => h('span', {}, '文本a'),
    key: 'bbb',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: '姓名',
        onInput: (val: string) => {
          console.log(val, 'input event')
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        rules: {
          required: true,
        },
      },
    ],
  },
  {
    label: 'labelSlot',
    children: [
      {
        component: 'select',
        field: 'gender',
        label: '性别',
        md: 12,
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        onFocus: () => {
          console.log('focus event')
        },
      },
      {
        component: 'el-date-picker',
        field: 'time',
        label: '出生日期',
        md: 12,
        fieldProps: {
          type: 'daterange',
          startPlaceholder: '开始日期',
          endPlaceholder: '结束日期',
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
      },
    ],
  },
  {
    slot: 'operate',
  },
]

function reset() {
  formRef.value.resetFields()
}

function submit() {
  formRef.value.validate((valid: boolean) => {
    if (valid) {
      ElMessage.success('成功')
      console.log(formData.value, 'config.formData')
    }
    else {
      console.log('error submit!!')
      return false
    }
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeCollapse="activeCollapse"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="collapse"
  >
    <template #labelSlot>
      <span>label自定义</span>
    </template>
    <template #operate>
      <div class="mt-4 w-full flex">
        <el-button class="w-full" @click="reset">
          重置
        </el-button>
        <el-button class="w-full" type="primary" @click="submit">
          提交
        </el-button>
      </div>
    </template>
  </z-form>
</template>

折叠属性

accordion属性直接传入ZForm组件。disabled属性传入column项中,可以禁用折叠项。

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'

const activeCollapse = ref('文本')
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

const options = {
  gender: [
    { label: '男', value: '1' },
    { label: '女', value: '2' },
  ],
}

const columns = [
  {
    label: '文本',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: '姓名',
        onInput: (val: string) => {
          console.log(val, 'input event')
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        rules: {
          required: true,
        },
      },
    ],
  },
  {
    label: '标题',
    children: [
      {
        component: 'select',
        field: 'gender',
        label: '性别',
        md: 12,
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        onFocus: () => {
          console.log('focus event')
        },
      },
      {
        component: 'el-date-picker',
        field: 'time',
        label: '出生日期',
        md: 12,
        fieldProps: {
          type: 'daterange',
          startPlaceholder: '开始日期',
          endPlaceholder: '结束日期',
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
      },
    ],
  },
  {
    label: '禁用',
    disabled: true,
    children: [
      {
        component: 'input',
        field: 'disabled',
        label: '禁用',
      },
    ],
  },
  {
    slot: 'operate',
  },
]

function reset() {
  formRef.value.resetFields()
}

function submit() {
  formRef.value.validate((valid: boolean) => {
    if (valid) {
      ElMessage.success('成功')
      console.log(formData.value, 'config.formData')
    }
    else {
      console.log('error submit!!')
      return false
    }
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeCollapse="activeCollapse"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="collapse"
    accordion
  >
    <template #operate>
      <div class="mt-4 w-full flex">
        <el-button class="w-full" @click="reset">
          重置
        </el-button>
        <el-button class="w-full" type="primary" @click="submit">
          提交
        </el-button>
      </div>
    </template>
  </z-form>
</template>

自定义内容

ZForm组件type属性为collapse时,column项可配置slotrender自定义折叠内容。

TIP

column项传入children字段(不管数组有没有长度),都会渲染ElCollapse的折叠项

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import { ElInput, ElMessage } from 'element-plus'

const activeCollapse = ref(['文本', '标题'])
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  address: '',
  input: '',
  time: [],
})

const options = {
  gender: [
    { label: '男', value: '1' },
    { label: '女', value: '2' },
  ],
}

const columns = [
  {
    label: '文本',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: '姓名',
        required: true,
      },
    ],
  },
  {
    label: '标题',
    render: () => h('span', 'custom content'),
    children: [],
  },
  {
    label: '地址',
    slot: 'addressSlot',
  },
  {
    label: '输入框',
    slot: 'input',
    required: true,
    message: '请输入文案',
  },
  {
    slot: 'operate',
  },
]

function reset() {
  formRef.value.resetFields()
}

function submit() {
  formRef.value.validate((valid: boolean) => {
    if (valid) {
      ElMessage.success('成功')
      console.log(formData.value, 'config.formData')
    }
    else {
      console.log('error submit!!')
      return false
    }
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeCollapse="activeCollapse"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="collapse"
  >
    <template #addressSlot>
      <div>自定义地址</div>
    </template>
    <template #input>
      <ElInput v-model="formData.input" />
    </template>
    <template #operate>
      <div class="mt-4 w-full flex">
        <el-button class="w-full" @click="reset">
          重置
        </el-button>
        <el-button class="w-full" type="primary" @click="submit">
          提交
        </el-button>
      </div>
    </template>
  </z-form>
</template>

折叠展开事件

collapse-change事件返回当前展开的折叠项label,直接绑定ZForm组件即可。

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'

const activeCollapse = ref(['文本', '标题'])
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

const options = {
  gender: [
    { label: '男', value: '1' },
    { label: '女', value: '2' },
  ],
}

const columns = [
  {
    label: '文本',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: '姓名',
        onInput: (val: string) => {
          console.log(val, 'input event')
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        rules: {
          required: true,
        },
      },
    ],
  },
  {
    label: '标题',
    children: [
      {
        component: 'select',
        field: 'gender',
        label: '性别',
        md: 12,
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        onFocus: () => {
          console.log('focus event')
        },
      },
      {
        component: 'el-date-picker',
        field: 'time',
        label: '出生日期',
        md: 12,
        fieldProps: {
          type: 'daterange',
          startPlaceholder: '开始日期',
          endPlaceholder: '结束日期',
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
      },
    ],
  },
  {
    slot: 'operate',
  },
]

function reset() {
  formRef.value.resetFields()
}

function submit() {
  formRef.value.validate((valid: boolean) => {
    if (valid) {
      ElMessage.success('成功')
      console.log(formData.value, 'config.formData')
    }
    else {
      console.log('error submit!!')
      return false
    }
  })
}

function handleCollapseChange(val: string) {
  console.log(val, 'val')
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeCollapse="activeCollapse"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="collapse"
    @collapse-change="handleCollapseChange"
  >
    <template #operate>
      <div class="mt-4 w-full flex">
        <el-button class="w-full" @click="reset">
          重置
        </el-button>
        <el-button class="w-full" type="primary" @click="submit">
          提交
        </el-button>
      </div>
    </template>
  </z-form>
</template>

折叠表单属性

属性名说明类型默认值
v-model:activeCollapse展开的collapse项(typecollapse生效)array / string
accordion手风琴模式booleanfalse

事件

事件名说明类型
update:modelValue表单项数据Function
update:activeCollapse折叠表单的展开项Function
collapse-change折叠表单折叠项改变时触发Function

Released under the MIT License.