Skip to content

Form Component ​

Overview ​

Form contains input boxes, radio buttons, dropdown selections, checkboxes and other user input components. Using forms, you can collect, validate and submit data.

Note

The Form component has been upgraded from 2.x Float layout to Flex layout.

Learning Objectives ​

  • Master the basic structure of el-form
  • Understand the usage of el-form-item form items
  • Learn form data binding (v-model)
  • Master form layout: inline, label-position
  • Understand form size control
  • Learn form disabled state
  • Master form reset and submission
  • Understand form validation mechanism

Basic Usage ​

Typical Form ​

The most basic form includes various input form items, such as input, select, radio, checkbox, etc. In each form component, you need a form-item field as a container for input items, used to get values and validate values.

vue
<template>
  <el-form :model="form" label-width="120px">
    <el-form-item label="Username">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item label="Password">
      <el-input v-model="form.password" type="password" />
    </el-form-item>
    <el-form-item label="Email">
      <el-input v-model="form.email" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">Submit</el-button>
      <el-button @click="onReset">Reset</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive } from 'vue'

const form = reactive({
  name: '',
  password: '',
  email: ''
})

const onSubmit = () => {
  console.log('submit!', form)
}

const onReset = () => {
  form.name = ''
  form.password = ''
  form.email = ''
}
</script>

Inline Form ​

When vertical space is limited and the form is relatively simple, you can put it in one line.

vue
<template>
  <el-form :inline="true" :model="formInline" class="demo-form-inline">
    <el-form-item label="Approved by">
      <el-input v-model="formInline.user" placeholder="Approved by" clearable />
    </el-form-item>
    <el-form-item label="Activity zone">
      <el-select v-model="formInline.region" placeholder="Activity zone" clearable>
        <el-option label="Zone one" value="shanghai" />
        <el-option label="Zone two" value="beijing" />
      </el-select>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">Query</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive } from 'vue'

const formInline = reactive({
  user: '',
  region: ''
})

const onSubmit = () => {
  console.log('submit!')
}
</script>

Label Alignment ​

Depending on your design, there are several different ways to align your label element.

vue
<template>
  <el-radio-group v-model="labelPosition" size="small">
    <el-radio-button label="left">Left</el-radio-button>
    <el-radio-button label="right">Right</el-radio-button>
    <el-radio-button label="top">Top</el-radio-button>
  </el-radio-group>
  <div style="margin: 20px" />
  <el-form
    :label-position="labelPosition"
    label-width="100px"
    :model="formLabelAlign"
    style="max-width: 460px"
  >
    <el-form-item label="Name">
      <el-input v-model="formLabelAlign.name" />
    </el-form-item>
    <el-form-item label="Activity zone">
      <el-input v-model="formLabelAlign.region" />
    </el-form-item>
    <el-form-item label="Activity form">
      <el-input v-model="formLabelAlign.type" />
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive, ref } from 'vue'

const labelPosition = ref('right')

const formLabelAlign = reactive({
  name: '',
  region: '',
  type: ''
})
</script>

Form Validation ​

Form component allows you to verify your data, helping you find and correct errors.

vue
<template>
  <el-form
    ref="ruleFormRef"
    :model="ruleForm"
    :rules="rules"
    label-width="120px"
    class="demo-ruleForm"
    :size="formSize"
    status-icon
  >
    <el-form-item label="Password" prop="pass">
      <el-input
        v-model="ruleForm.pass"
        type="password"
        autocomplete="off"
      />
    </el-form-item>
    <el-form-item label="Confirm" prop="checkPass">
      <el-input
        v-model="ruleForm.checkPass"
        type="password"
        autocomplete="off"
      />
    </el-form-item>
    <el-form-item label="Age" prop="age">
      <el-input v-model.number="ruleForm.age" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">
        Submit
      </el-button>
      <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive, ref } from 'vue'
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'

interface RuleForm {
  pass: string
  checkPass: string
  age: number
}

const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
  pass: '',
  checkPass: '',
  age: 0
})

const validatePass = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('Please input the password'))
  } else {
    if (ruleForm.checkPass !== '') {
      if (!ruleFormRef.value) return
      ruleFormRef.value.validateField('checkPass', () => null)
    }
    callback()
  }
}
const validatePass2 = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('Please input the password again'))
  } else if (value !== ruleForm.pass) {
    callback(new Error("Two inputs don't match!"))
  } else {
    callback()
  }
}

const rules = reactive<FormRules<RuleForm>>({
  pass: [{ validator: validatePass, trigger: 'blur' }],
  checkPass: [{ validator: validatePass2, trigger: 'blur' }],
  age: [
    { required: true, message: 'Please input age', trigger: 'blur' },
    { type: 'number', message: 'Age must be a number', trigger: 'blur' }
  ]
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
</script>

Custom Validation Rules ​

This example shows how to customize your own validation rules to finish a two-factor password verification.

vue
<template>
  <el-form
    ref="ruleFormRef"
    :model="ruleForm"
    :rules="rules"
    label-width="120px"
    class="demo-ruleForm"
  >
    <el-form-item label="Password" prop="pass">
      <el-input
        v-model="ruleForm.pass"
        type="password"
        autocomplete="off"
      />
    </el-form-item>
    <el-form-item label="Confirm" prop="checkPass">
      <el-input
        v-model="ruleForm.checkPass"
        type="password"
        autocomplete="off"
      />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">
        Submit
      </el-button>
      <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'

const ruleFormRef = ref<FormInstance>()

const checkAge = (rule: any, value: any, callback: any) => {
  if (!value) {
    return callback(new Error('Please input the age'))
  }
  setTimeout(() => {
    if (!Number.isInteger(value)) {
      callback(new Error('Please input digits'))
    } else {
      if (value < 18) {
        callback(new Error('Age must be greater than 18'))
      } else {
        callback()
      }
    }
  }, 1000)
}

const validatePass = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('Please input the password'))
  } else {
    if (ruleForm.checkPass !== '') {
      if (!ruleFormRef.value) return
      ruleFormRef.value.validateField('checkPass', () => null)
    }
    callback()
  }
}

const validatePass2 = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('Please input the password again'))
  } else if (value !== ruleForm.pass) {
    callback(new Error("Two inputs don't match!"))
  } else {
    callback()
  }
}

const ruleForm = reactive({
  pass: '',
  checkPass: '',
  age: ''
})

const rules = reactive<FormRules>({
  pass: [{ validator: validatePass, trigger: 'blur' }],
  checkPass: [{ validator: validatePass2, trigger: 'blur' }],
  age: [{ validator: checkAge, trigger: 'blur' }]
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
</script>

API Reference ​

Form Attributes ​

AttributeDescriptionTypeAccepted ValuesDefault
modeldata of form componentobject——
rulesvalidation rules of formobject——
inlinewhether the form is inlineboolean—false
label-positionposition of label. If set to 'left' or 'right', label-width prop is also requiredstringleft / right / topright
label-widthwidth of label, e.g. '50px'. All its direct child form-items will inherit this value. Width auto is supported.string / number——
label-suffixsuffix of the labelstring——
hide-required-asteriskwhether to hide required fields should have a red asterisk (star) beside their labelsboolean—false
require-asterisk-positionposition of asteriskstringleft / rightleft
show-messagewhether to show the error messageboolean—true
inline-messagewhether to display the error message inline with the form itemboolean—false
status-iconwhether to display an icon indicating the validation resultboolean—false
validate-on-rule-changewhether to trigger validation when the rules prop is changedboolean—true
sizecontrol the size of components in this formstringlarge / default / small—
disabledwhether to disable all components in this form. If set to true, it cannot be overridden by its inner components' disabled propboolean—false
scroll-to-errorWhen validation fails, scroll to the first error form entryboolean—false

Form Methods ​

MethodDescriptionParameters
validatevalidate the whole form. Takes a callback as a param. After validation, the callback will be executed with two params: a boolean indicating if the validation has passed, and an object containing all fields that fail the validation. Returns a promise if callback is omittedFunction(callback: Function(boolean, object))
validateFieldvalidate one or several form itemsFunction(props: array | string, callback: Function(errorMessage: string))
resetFieldsreset all the fields and remove validation result—
scrollToFieldscroll to the specified form fieldFunction(prop: string)
clearValidateclear validation message for certain fields. The parameter is prop name or an array of prop names of the form items whose validation messages will be removed. When omitted, all fields' validation messages will be removedFunction(props: array | string)

Form Events ​

Event NameDescriptionParameters
validatetriggers after a form item is validatedprop name of the form item being validated, whether validation is passed and the error message if not

Form Slots ​

NameDescription
—content of Form

FormItem Attributes ​

AttributeDescriptionTypeAccepted ValuesDefault
propa key of model. In the use of validate and resetFields method, the attribute is requiredstringkeys of model that passed to form—
labellabelstring——
label-widthwidth of label, e.g. '50px'. Width auto is supported.string / number——
requiredwhether the field is required or not, will be determined by validation rules if omittedboolean—false
rulesvalidation rules of form, see the following table, more advanced usage at async-validatorobject / array——
errorfield error message, set its value and the field will validate error and show this message immediatelystring——
show-messagewhether to show the error messageboolean—true
inline-messageinline style validate messageboolean—false
sizecontrol the size of components in this form-itemstringlarge / default / small—

FormItem Slots ​

NameDescription
—content of Form Item
labelcontent of Form Item label
errorcontent of Form Item error message

FormItem Methods ​

MethodDescriptionParameters
resetFieldreset current field and remove validation result—
clearValidateremove validation status of the field—

Best Practices ​

  1. Use appropriate validation: Implement both client-side and server-side validation
  2. Provide clear feedback: Show validation errors immediately and clearly
  3. Group related fields: Use logical grouping for better user experience
  4. Consider accessibility: Ensure proper labeling and keyboard navigation
  5. Handle loading states: Show loading indicators during form submission
  6. Preserve user input: Don't clear forms unnecessarily

Common Use Cases ​

Login Form ​

vue
<template>
  <el-form :model="loginForm" :rules="loginRules" ref="loginFormRef">
    <el-form-item prop="username">
      <el-input v-model="loginForm.username" placeholder="Username" />
    </el-form-item>
    <el-form-item prop="password">
      <el-input v-model="loginForm.password" type="password" placeholder="Password" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="handleLogin">Login</el-button>
    </el-form-item>
  </el-form>
</template>

Registration Form ​

vue
<template>
  <el-form :model="registerForm" :rules="registerRules" ref="registerFormRef">
    <el-form-item label="Email" prop="email">
      <el-input v-model="registerForm.email" />
    </el-form-item>
    <el-form-item label="Password" prop="password">
      <el-input v-model="registerForm.password" type="password" />
    </el-form-item>
    <el-form-item label="Confirm Password" prop="confirmPassword">
      <el-input v-model="registerForm.confirmPassword" type="password" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="handleRegister">Register</el-button>
    </el-form-item>
  </el-form>
</template>

Element Plus Study Guide