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.