Skip to content

StepForm

Based on ZForm component and ElStep component encapsulation.

Step Form

Pass step to form type type, configure children (form items) in columns to implement step form. Current step is bound through activeStep two-way binding.

Configure label, description, icon and status in column to set step text, description, icon and status.

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

const activeStep = ref(0)
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

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

const columns = [
  {
    label: 'Step 1',
    description: 'Description',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: 'Name',
        tooltip: 'Name',
        extra: 'Name',
        onInput: (val: string) => {
          console.log(val, 'input event')
        },
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        required: true,
      },
    ],
  },
  {
    label: () => h('span', {}, 'Step 2'),
    description: () => h('span', {}, 'Description'),
    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')
        },
      },
    ],
  },
]

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

function submit() {
  console.log(formData.value, 'success')
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeStep="activeStep"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="step"
    @submit="submit"
  />
</template>

Step Attributes

el-step component attributes, such as: process-status, finish-status, align-center, etc., are passed directly through z-form.

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

const activeStep = ref(0)
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

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

const columns = [
  {
    label: 'Step 1',
    description: 'Description',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: 'Name',
        required: true,
      },
    ],
  },
  {
    label: () => h('span', {}, 'Step 2'),
    description: () => h('span', {}, 'Description'),
    children: [
      {
        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() {
  console.log(formData.value, 'success')
}
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeStep="activeStep"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="step"
    process-status="error"
    finish-status="success"
    @submit="submit"
  />
</template>

Customization

Supports customizing label, description, icon content of column items. As usual, supports passing render or strings with slot (case insensitive).

<script lang="ts" setup>
import { h, ref } from 'vue'

const activeStep = ref(0)
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

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

const columns = [
  {
    label: 'firstLabelSlot',
    description: 'firstDescSlot',
    children: [
      {
        component: 'input',
        field: 'name',
        label: 'Name',
        required: true,
      },
    ],
  },
  {
    label: () => h('span', {}, 'Step 2'),
    description: () => h('span', {}, 'Description'),
    children: [
      {
        component: 'select',
        field: 'gender',
        label: 'Gender',
        required: true,
      },
      {
        component: 'el-date-picker',
        field: 'time',
        label: 'Date',
        fieldProps: {
          type: 'daterange',
          startPlaceholder: 'Start date',
          endPlaceholder: 'End date',
        },
      },
    ],
  },
]
</script>

<template>
  <z-form
    ref="formRef"
    v-model="formData"
    v-model:activeStep="activeStep"
    :options="options"
    :columns="columns"
    label-width="80px"
    size="default"
    type="step"
  >
    <template #firstLabelSlot>
      <span>custom label</span>
    </template>
    <template #firstDescSlot>
      <span>custom description</span>
    </template>
  </z-form>
</template>

Configure footer slot or render function to customize step bottom content.

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

const activeStep = ref(0)
const formRef = ref()
const formData = ref({
  name: '',
  gender: '',
  time: [],
})

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

const columns = [
  {
    label: 'Step 1',
    description: 'Description',
    children: [
      {
        component: 'input',
        field: 'name',
        modifier: 'trim',
        label: 'Name',
        required: true,
      },
    ],
  },
  {
    label: 'Step 2',
    description: 'Description',
    children: [
      {
        component: 'select',
        field: 'gender',
        label: 'Gender',
        onChange: (val: string) => {
          console.log(val, 'change event')
        },
        onFocus: () => {
          console.log('focus event')
        },
        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')
        },
      },
    ],
  },
]

function handlePrevious() {
  activeStep.value--
}

function handleNext() {
  formRef.value.validate((val: boolean) => {
    if (val)
      activeStep.value++
  })
}

function submit() {
  formRef.value.validate((val: boolean) => {
    if (val) {
      ElMessage.success('success')
      console.log(formData.value, 'success')
    }
  })
}
</script>

<template>
  <z-form
    ref="formRef" v-model="formData" v-model:activeStep="activeStep" :options="options" :columns="columns"
    label-width="80px" size="default" type="step"
  >
    <template #footer>
      <el-button :disabled="activeStep === 0" @click="handlePrevious">
        Previous
      </el-button>
      <el-button :disabled="activeStep === 1" @click="handleNext">
        Next
      </el-button>
      <el-button v-if="activeStep === 1" @click="submit">
        Submit
      </el-button>
    </template>
  </z-form>
</template>

Step Form Attributes

AttributeDescriptionTypeDefault
modelValue:activeStepCurrent stepnumber0
process-statusSet current step statuswait / process / finish / error / successprocess
finish-statusSet finish step statuswait / process / finish / error / successfinish
align-centerCenter alignmentbooleantrue

Released under the MIT License.