Search code examples
javascripttypescriptvue.jsvalidationelement-ui

Element ui's form validation isn't working on vue 2 composition api


I'm making a form that can be validated using element UI's form validation on vue 2 composition API environment.

A form is nesting the table inside, so its structure is quite complicated.

...
<div>
    <el-form
      ref="smKeyInfoForm"
      :model="formData"
      :rules="formRules">
      <el-table
        :data="tableData"
        ...
      >
        <el-table-column
          v-for="option in tableOptions"
          :key="option.prop"
          :prop="option.prop"
          ...
        >
          <template slot-scope="scope">
            <el-form-item :prop="scope.row[option.prop].prop">
                  <el-input
                    v-model="formData[scope.row[option.prop].prop]"
                  />
...
<script lang="ts">
...
const formRules: { [key: string]: FormRule[]} = {
  smName: [{ required: true, trigger: 'blur' }],
  clientId: [{ required: true, trigger: 'blur' }],
  ...
}
...
const formData = {
      smName: '',
      clientId: '',
...
}).then(() => {
        (smKeyInfoForm.value as unknown as ElForm).validate(async (valid) => {
          if (valid) {
...

SomethingTab.vue

When I validate a form without the required field (ex. smName = ''), the 'valid' value of the validator returns true.

By checking with Chrome DevTools Vue extensions, I found that all props of el-form-item are normally registered, and v-model is connected to an adequate field.

How can I fix this validation problem?


Solution

  • I found that it's caused when switching table's element from plain div to form-item and vice versa.

    ...
    <div v-else-if="scope.row[option.prop].type === 'radios'">
                      <el-radio-group v-model="formData[scope.row[option.prop].prop]">
                        <el-radio
                          v-for="radioOption in scope.row[option.prop].options"
                          :key="radioOption.value"
                          :label="radioOption.value"
                        >
                          {{ radioOption.label }}
                        </el-radio>
                      </el-radio-group>
                    </div>
                    <div v-else>
                      {{ scope.row[option.prop] }}
                    </div>
                  </div>
                </el-form-item>
    

    The form shows 'divs' in show-mode and other form elements like radios in edit mode. I guess that form validation didn't work normally when switching into form-element.

    So I add key to form and I change it when I toggle the show-edit mode and it works.

    ...
     <el-form
          ...
          :key="formReRenderKey"
          :model="formData"
          :rules="formRules">
    ...
        const onClickBtn = () => {
            ...
            isOnModification.value = true
    
            formReRenderKey.value++
    ...