Search code examples
javascripttypescriptvue.jsvuejs3element-plus

Vue 3 Typescript unable to access method from ref


Hi everyone I'm new to Vue 3 and Typescript and I'm having hard time trying to solve typescript error on my project below is the typescript error.

It's not able to find validate method but it's showing when I try to console it.

Property 'validate' does not exist on type 'string'.

enter image description here

I'm using Vue 3 composition api with typescript and Vue Element Plus, below is my component code.

Component

    <template>
  <div class="w-full h-full absolute flex">
    <el-form
      class="w-4/5 sm:w-1/2 lg:w-1/3 xl:w-1/4 m-auto"
      :ref="formRef"
      :model="form"
      :rules="rules"
    >
      <h2>Login</h2>
      <el-form-item label="Email" prop="email">
        <el-input
          type="email"
          autocomplete="off"
          v-model="form.email"
        />
      </el-form-item>
      <el-form-item label="Password" prop="password">
        <el-input
          type="password"
          autocomplete="off"
          v-model="form.password"
        />
      </el-form-item>
      <el-form-item>
        <el-button
          type="success"
          class="w-full"
          @click="handleLogin"
        >Submit</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script lang="ts">
import { defineComponent, onBeforeMount, onMounted, reactive, ref } from "vue";
export default defineComponent({
  name: "Login",
  setup() {
    const form = reactive({
      email: "",
      password: ""
    });
    const rules = ref({
      email: [{
        required: true,
        message: "Email is required",
        trigger: "blur"
      }],
      password: [{
        required: true,
        message: "Password is required",
        trigger: "blur"
      }]
    });
    const formRef = ref("formRef");

    const handleLogin = () => {
      console.log(formRef)
      // Property 'validate' does not exist on type 'string'.
      formRef.value?.validate((valid: boolean) => {
        console.log(valid);
      });
    };

    onMounted(() => {
      console.log("Login mounted");
    });

    onBeforeMount(() => {
      console.log("Login onBeforeMount");
    });

    return {
      formRef,
      form,
      rules,
      handleLogin
    };
  }
});
</script>

Solution

  • There is a few mistakes. ref receives a primitive type string, boolean, etc... for objects use reactive.

    so you should define rules using reactive not ref.

    const rules = reactive({
          email: [{
            required: true,
            message: "Email is required",
            trigger: "blur"
          }],
          password: [{
            required: true,
            message: "Password is required",
            trigger: "blur"
          }]
        });
    

    You don't need to bind your ref so do this way:

     <el-form
              class="w-4/5 sm:w-1/2 lg:w-1/3 xl:w-1/4 m-auto"
              ref="formRef"
              :model="form"
              :rules="rules"
            >
    

    And I recommend you to declare you formRef using the html casting objects.

    like this:

    const formRef = ref<HTMLFormElement>();
    

    I hope it help you =)