Skip to content

ArrayForm

Based on ZForm component encapsulation.

Array Form

Pass array to form type type, configure children (form items) in columns to implement array form.

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

interface FormData {
  name: string
  gender: string
  address: string
  time: string[]
}

const formRef = ref()
const form = ref<FormData[]>([{
  name: '',
  gender: '',
  address: '',
  time: [],
}])

const options = {
  gender: [
    { label: 'Male', value: '1' },
    { label: 'Female', value: '2' },
  ],
}

const columns = [
  {
    component: 'input',
    field: 'name',
    modifier: 'trim',
    label: 'Name',
    onInput: (val: string) => {
      console.log(val, 'input event')
    },
    onChange: (val: string) => {
      console.log(val, 'change event')
    },
    required: true,
  },
  {
    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')
    },
  },
  {
    slot: 'address',
    label: 'Address',
  },
]

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

function submit() {
  formRef.value.validate((valid: boolean, fields: ValidateField) => {
    console.log(form.value, fields, 'config.formData')
    if (valid)
      ElMessage.success('success')

    else
      console.log('error')
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="form"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="small"
    type="array"
  >
    <template #address="{ formData }">
      <el-input v-model="formData.address" />
    </template>
  </z-form>
  <div class="mt-4 w-full flex">
    <el-button class="w-full" @click="reset">
      Reset
    </el-button>
    <el-button type="primary" class="w-full" @click="submit">
      Submit
    </el-button>
  </div>
</template>

Inline Array Form

Complex inline array form example. To validate form items, you can directly call the form validate method.

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

const formRef = ref()
const form = ref({
  time: [],
  a: [
    {
      name: '',
      gender: '',
      time: [],
    },
  ],
  b: [
    {
      name: '',
      gender: '',
      address: '',
      time: [],
    },
  ],
})

const options = {
  gender: [
    { label: 'Male', value: '1' },
    { label: 'Female', value: '2' },
  ],
}

const columns = [
  {
    label: 'Text 1',
    field: 'a',
    max: 2,
    children: [
      {
        component: 'input',
        field: 'name',
        label: 'Name',
        onInput: (val: string) => {
          console.log(val, 'input event')
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        required: true,
      },
    ],
  },
  {
    label: 'Text 2',
    field: 'b',
    extra: 'extra field',
    tooltip: 'Hint',
    children: [
      {
        component: 'select',
        field: 'gender',
        label: 'Gender',
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        onFocus: () => {
          console.log('focus event')
        },
        rules: {
          required: true,
        },
      },
      {
        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')
        },
      },
      {
        slot: 'test',
        field: 'address',
        label: 'Address',
      },
    ],
  },
  {
    label: 'input',
    component: 'input',
    field: 'input',
  },
  {
    slot: 'operate',
  },
]

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

function submit() {
  formRef.value.validate((valid: boolean, fields: ValidateField) => {
    console.log(form.value, fields, 'config.formData')
    if (valid)
      ElMessage.success('success')

    else
      console.log('error')
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="form"
    :options="options"
    :columns="columns"
    :max="3"
    label-width="80px"
    size="default"
    type="array"
  >
    <template #test="{ formData }">
      <el-input v-model="formData.address" />
    </template>
    <template #operate>
      <div class="w-full flex">
        <el-button class="w-full" @click="reset">
          Reset
        </el-button>
        <el-button type="primary" class="w-full" @click="submit">
          Submit
        </el-button>
      </div>
    </template>
  </z-form>
</template>

Maximum Quantity

Set maximum quantity through max attribute.

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

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',
    modifier: 'trim',
    label: 'Name',
    required: true,
  },
  {
    component: 'select',
    field: 'gender',
    label: 'Gender',
  },
  {
    component: 'el-date-picker',
    field: 'time',
    label: 'Date',
    fieldProps: {
      type: 'daterange',
      startPlaceholder: 'Start date',
      endPlaceholder: 'End date',
    },
  },
]

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

function submit() {
  formRef.value.validate((valid: boolean, fields: ValidateField) => {
    console.log(formData.value, fields, 'config.formData')
    if (valid)
      ElMessage.success('success')

    else
      console.log('error')
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    :options="options"
    :columns="columns"
    :max="2"
    label-width="80px"
    size="small"
    type="array"
  />
  <div class="mt-4 w-full flex">
    <el-button class="w-full" @click="reset">
      Reset
    </el-button>
    <el-button type="primary" class="w-full" @click="submit">
      Submit
    </el-button>
  </div>
</template>

Minimum Quantity

Set minimum quantity through min attribute.

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

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',
    modifier: 'trim',
    label: 'Name',
    required: true,
  },
  {
    component: 'select',
    field: 'gender',
    label: 'Gender',
  },
  {
    component: 'el-date-picker',
    field: 'time',
    label: 'Date',
    fieldProps: {
      type: 'daterange',
      startPlaceholder: 'Start date',
      endPlaceholder: 'End date',
    },
  },
]

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

function submit() {
  formRef.value.validate((valid: boolean, fields: ValidateField) => {
    console.log(formData.value, fields, 'config.formData')
    if (valid)
      ElMessage.success('success')

    else
      console.log('error')
  })
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    :options="options"
    :columns="columns"
    :min="1"
    label-width="80px"
    size="small"
    type="array"
  />
  <div class="mt-4 w-full flex">
    <el-button class="w-full" @click="reset">
      Reset
    </el-button>
    <el-button type="primary" class="w-full" @click="submit">
      Submit
    </el-button>
  </div>
</template>

Operations

Configure action as false to disable operation items.

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

interface FormData {
  name: string
  gender: string
  address: string
  time: string[]
}

const formRef = ref()
const form = ref<FormData[]>([{
  name: '',
  gender: '',
  address: '',
  time: [],
}])

const options = {
  gender: [
    { label: 'Male', value: '1' },
    { label: 'Female', value: '2' },
  ],
}

const columns = [
  {
    component: 'input',
    field: 'name',
    modifier: 'trim',
    label: 'Name',
    required: true,
  },
  {
    component: 'select',
    field: 'gender',
    label: 'Gender',
  },
  {
    component: 'el-date-picker',
    field: 'time',
    label: 'Date',
    fieldProps: {
      type: 'daterange',
      startPlaceholder: 'Start date',
      endPlaceholder: 'End date',
    },
  },
  {
    slot: 'address',
    label: 'Address',
  },
]

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

function submit() {
  formRef.value.validate((valid: boolean, fields: ValidateField) => {
    console.log(form.value, fields, 'config.formData')
    if (valid)
      ElMessage.success('success')

    else
      console.log('error')
  })
}

function handleAdd() {
  form.value.push({})
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="form"
    :options="options"
    :columns="columns"
    :action="false"
    label-width="80px"
    size="small"
    type="array"
  >
    <template #address="{ formData }">
      <el-input v-model="formData.address" />
    </template>
  </z-form>
  <el-button class="mt-1 w-full" type="warning" @click="handleAdd">
    Add
  </el-button>
  <div class="mt-4 w-full flex">
    <el-button class="w-full" @click="reset">
      Reset
    </el-button>
    <el-button type="primary" class="w-full" @click="submit">
      Submit
    </el-button>
  </div>
</template>

Configure action as slot or render function to customize operation items.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import { ElIcon, ElMessage } from 'element-plus'
import { Delete } from '@element-plus/icons-vue'
import type { ValidateField } from 'ideaz-element'

interface FormData {
  name: string
  gender: string
  address: string
  time: string[]
}

const formRef = ref()
const form = ref<FormData[]>([{
  name: '',
  gender: '',
  address: '',
  time: [],
}])

const options = {
  gender: [
    { label: 'Male', value: '1' },
    { label: 'Female', value: '2' },
  ],
}

const columns = [
  {
    component: 'input',
    field: 'name',
    modifier: 'trim',
    label: 'Name',
    required: true,
  },
  {
    component: 'select',
    field: 'gender',
    label: 'Gender',
  },
  {
    component: 'el-date-picker',
    field: 'time',
    label: 'Date',
    fieldProps: {
      type: 'daterange',
      startPlaceholder: 'Start date',
      endPlaceholder: 'End date',
    },
  },
  {
    slot: 'address',
    label: 'Address',
  },
]

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

function submit() {
  formRef.value.validate((valid: boolean, fields: ValidateField) => {
    console.log(form.value, fields, 'config.formData')
    if (valid)
      ElMessage.success('success')

    else
      console.log('error')
  })
}

function handleDelete(index: number) {
  form.value.splice(index, 1)
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="form"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="small"
    type="array"
  >
    <template #address="{ formData }">
      <el-input v-model="formData.address" />
    </template>
    <template #action="{ index }">
      <ElIcon size="16" class="delete cursor-pointer" @click="handleDelete(index)">
        <Delete />
      </ElIcon>
    </template>
  </z-form>
  <div class="mt-4 w-full flex">
    <el-button class="w-full" @click="reset">
      Reset
    </el-button>
    <el-button type="primary" class="w-full" @click="submit">
      Submit
    </el-button>
  </div>
</template>

<style lang="scss" scoped>
.delete {
  position: absolute;
  top: -8px;
  right: 0;
  color: red;
}
</style>

Array Form Attributes

AttributeDescriptionTypeDefault
maxMaximum form itemsnumber
minMinimum form itemsnumber
actionOperation itemsboolean / () => VNodetrue

Released under the MIT License.