FormItems 表单项

快速的数据化配置一个表单。

FormGrid,FormDesc,FormTableEditor 等表单布局组件都适用以下规则。

典型表单

使用内置数据化的表单项组件比如 agel-selectagel-radioagel-checkbox等,可快速完成一个包含各种输入表单项的基础表单。

属性 slot 指定要渲染的组件实例或组件名称,若传递的是组件名称,需要保证该组件已经全局导入。

属性 attrs 为其组件提供属性支持,使用驼峰命名法。

属性 required 将自动生成由 label 组成的必填规则。

使用 getRef 可以获取表单子组件的组件的实例对象。

点击查看代码
<template>
  <ElForm :model="form.model" label-width="auto" class="demo">
    <AgelFormItems ref="formLayoutRef" :items="form.items"></AgelFormItems>
  </ElForm>
</template>

<script lang="tsx" setup>
import { reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'

const formLayoutRef = ref()
const form = reactive({
  model: {},
  items: [
    {
      prop: 'name',
      label: 'Activity name',
      required: true
    },
    {
      prop: 'zone',
      label: 'Activity zone',
      slot: 'agel-select',
      attrs: {
        options: [
          { label: 'Zone one', value: 'shanghai' },
          { label: 'Zone two', value: 'beijing' }
        ],
        onChange: (v: string) => {
          ElMessage({
            message: `change ${v}`,
            type: 'success'
          })
        }
      }
    },
    {
      prop: 'date',
      label: 'Activity date',
      slot: 'el-date-picker'
    },
    {
      prop: 'delivery',
      label: 'Instant delivery',
      slot: 'el-switch'
    },
    {
      prop: 'type',
      label: 'Activity type',
      slot: 'agel-checkbox',
      attrs: {
        options: ['Online activities', 'Promotion activities', 'Offline activities', 'Simple brand exposure']
      }
    },
    {
      prop: 'resources',
      label: 'Resources',
      slot: 'agel-radio',
      attrs: { options: ['Sponsor', 'Venue'] }
    },
    {
      prop: 'decs',
      label: 'Activity Form',
      attrs: { type: 'textarea' }
    },
    {
      slot: 'ElButton',
      slots: () => 'Create',
      attrs: {
        type: 'primary',
        onClick: () => {
          formLayoutRef.value?.validate()
          formLayoutRef.value?.getRef('zone').focus()
        }
      }
    }
  ]
})
</script>

插槽表单

属性 slot label 可以为一个渲染函数,使用 jsx 大幅提高体验。

属性 slot 支持模板插槽,但必须 slot- 开头,否则会被识别为组件名称。

属性 slots 可以实现表单项组件的子插槽的渲染。

点击查看代码
<template>
  <ElForm :model="form.model" label-width="auto" class="demo __fullwidth">
    <AgelFormItems :items="form.items">
      <template #slot-date>
        <el-button>自定义 slot2</el-button>
      </template>
    </AgelFormItems>
  </ElForm>
</template>

<script lang="tsx" setup>
import { reactive } from 'vue'

const form = reactive({
  model: {},
  items: [
    {
      label: () => <el-tag>自定义 label</el-tag>,
      slot: () => <el-button>自定义 slot1</el-button>
    },
    {
      label: '模板插槽',
      slot: 'slot-date'
    },
    {
      label: '组件子插槽',
      slot: 'el-input',
      slots: {
        prepend: () => 'http://',
        append: () => '.com'
      }
    }
  ]
})
</script>

联动表单

得益于 vue3 的 进步,数据化配置也可以通过 computed 简单快速的实现表单之间的联动。

点击查看代码
<template>
  <ElForm :model="model" label-width="auto" class="demo">
    <AgelFormItems :items="items"></AgelFormItems>
  </ElForm>
</template>

<script lang="tsx" setup>
import { reactive, ref, computed } from 'vue'

const model = reactive({
  grade: '很棒'
})

const options = ref<string[]>([])

const items = ref([
  {
    label: '打分',
    prop: 'grade',
    slot: 'agel-radio',
    attrs: {
      options: ['很棒', '很糟糕']
    }
  },
  {
    label: '分数',
    prop: 'number',
    loading: computed(() => options.value.length == 0),
    slot: 'agel-select',
    attrs: {
      class:'w100',
      options: computed(() => options.value)
    }
  },
  {
    label: '好评',
    prop: 'good',
    hidden: computed(() => model.grade == '很糟糕'),
  },
  {
    label: '差评',
    prop: 'good',
    hidden: computed(() => model.grade == '很棒'),
    attrs: {
      disabled: computed(() => model.grade == '很糟糕'),
    }
  },
  {
    slot: 'ElButton',
    slots: () => '获取分数',
    attrs: {
      type: 'primary',
      onClick: getOption
    },
  }
])


function getOption() {
  // 模拟接口
  options.value = []
  setTimeout(() => {
    options.value = Array.from({ length: 10 }).map((v, i) => (i + 1) + '分')
  }, 2000);
}

getOption()
</script>

动态表单

设置 modelProp 为表单项提供动态 prop,值得注意是 v-for 的 key 需指定为 index。

设置 scope 属性为 slot 渲染函数/插槽 提供作用域参数。

点击查看代码
<template>
  <ElForm label-width="auto" :model="model" class="demo" inline>
    <AgelFormItems
      v-for="(rowData, rowIndex) in model.domains"
      :items="domainsItems"
      :model-prop="'domains.' + rowIndex"
      :key="rowIndex"
      :scope="{ rowData, rowIndex }"
    >
    </AgelFormItems>

    <ElFormItem>
      <ElButton type="primary" @click="model.domains.push({ phone: String(model.domains.length + 1) })">添加</ElButton>
    </ElFormItem>
  </ElForm>
</template>

<script lang="tsx" setup>
import { reactive } from 'vue'

const model = reactive({
  domains: [{ phone: '1' }, { phone: '2' }]
})

const domainsItems = [
  { slot: ({ rowIndex }: any) => <b>动态表单{rowIndex + 1}</b>, class: 'w100' },
  { prop: 'phone', label: ({ rowIndex }: any) => '手机号码' + (rowIndex + 1) },
  { prop: 'email', label: '联系邮件' },
  {
    span: 4,
    labelWidth: 0,
    slot: ({ rowIndex }: any) => {
      return <el-button onClick={() => model.domains.splice(rowIndex, 1)}>删除</el-button>
    }
  }
]
</script>



 

































属性

属性类型默认值说明
itemsItemProps[]-表单配置项
view-modelboolean-视图模式,只渲染 value
model-propstring-表单 model 键名
scopeobject-表单项插槽作用域参数

ItemProps

属性类型默认值说明
propstring-model 键名,支持 'obj.xx.xx'
labelstring | RenderFunction-标签文本
requiredboolean-自动生成必填规则
slotstring | Component | RenderFunctionElInput表单项组件
slotsSlots | RenderFunction-表单项组件的插槽
attrsobject-表单项组件的属性
viewModelboolean-视图模式,只渲染 value
viewFormatRenderFunction-视图模式的格式化工具
vmodel'.trim' | '.number'-v-model 修饰符
loadingboolean-是否显示加载
hiddenboolean-是否隐藏
classstring-formitem class
labelWidth, rules, error, showMessage, inlineMessage...ElFormIten 属性open in new window

方法

名称参数说明
getRefprop获取组件实例
validate(callback)=>Promise对整个 items 表单进行验证
resetFieldsprops重置表单

插槽

名称插槽作用域说明
slot-xxitemPropsitem 组件具名插槽
Last Updated:
Contributors: liujianfeng, agrass