Typescript in vue - Property 'validate' does not exist on type 'Vue | Element | Vue[] | Element[]'.

后端 未结 5 1734
感动是毒
感动是毒 2020-12-23 17:38

I created v-form like this


  ...
  

        
相关标签:
5条回答
  • 2020-12-23 18:04

    If you use vue-class-component with vue-property-decorator you can do it like this:

    Define in a types.ts a new Type with the vuetify form functions:

    export type VForm = Vue & {
      validate: () => boolean;
      resetValidation: () => boolean;
      reset: () => void;
    };
    

    Then import in your component:

    import { VForm } from "types";
    import { Component, Ref} from "vue-property-decorator";
    

    Use @Ref in your component to define the form:

    export default class YourComponent extends Vue {
      @Ref("form") readonly form!: VForm;
    }
    

    so in your methods you can use it like this:

    this.form.validate();
    this.form.resetValidation();
    this.form.reset();
    
    0 讨论(0)
  • 2020-12-23 18:05

    Couldn't comment on the accepted solution since I'm new to StackOverflow and wanted to provide my solution to this. I took the same initial step to investigate as OP and did a console.log(this.$ref.form), the output on the console is actually an array of [VueComponent] and validate() function doesn't exist in that context.

    I was able to access the validate() function on the form by doing this.$ref.form[0].validate()

    0 讨论(0)
  • 2020-12-23 18:10

    None of the answers did it. I was trying to get the validate then promise to work on a form.

    As per comment

    if you are building your vue component in typescript using

    export default Vue.extend({})
    

    then do

    import { ValidationObserver, ValidationProvider, extend } from "vee-validate";
    import { required } from "vee-validate/dist/rules";
    import Vue, { VueConstructor } from "vue";
    export default (Vue as VueConstructor<
      Vue & {
        $refs: {
          form: InstanceType<typeof ValidationProvider>;
        };
      }
    >).extend({
      methods: {
        saveEntity() {
          if (this.loading) return;
          console.log(this.entity);
          this.$refs.form.validate().then(success => {
            if (!success) {
              console.log("not valid");
              return;
            }
            console.log("valid");
          });
        }
      }
    })
    

    This validates the ValidationObserver ref="form" just fine.

    0 讨论(0)
  • 2020-12-23 18:12
    let form: any = this.$refs.form
    if(form.validate){}
    
    0 讨论(0)
  • 2020-12-23 18:16

    Solutions:

    Simple:

    (this.$refs.form as Vue & { validate: () => boolean }).validate()
    

    Alternative (use this if you reference this.$refs.form multiple times in your component):

    computed: {
      form(): Vue & { validate: () => boolean } {
        return this.$refs.form as Vue & { validate: () => boolean }
      }
    } // Use it like so: this.form.validate()
    

    Reusable (use this if you use the v-form component multiple times across your application):

    // In a TS file
    export type VForm = Vue & { validate: () => boolean }
    
    // In component, import `VForm`
    computed: {
      form(): VForm {
        return this.$refs.form as VForm
      }
    }
    

    Explanation:

    In the Vue template syntax, we can use the ref attribute on a Vue instance or a DOM element. If ref is used in a v-for loop, an array of Vue instances or DOM elements is retreived.

    This is why this.$refs can either return Vue | Element | Vue[] | Element[].

    In order for TypeScript to know which type is being used, we need to cast the value.

    We can either do:

    (this.$refs.form as Vue).validate() or (<Vue>this.$refs.form).validate()

    We cast it to Vue because v-form is a Vue instance (component) and not an Element.

    My personal preference is to create a computed property which returns the Vue instance(s) or DOM element(s) already casted.

    ie.

    computed: {
      form(): Vue {
        return this.$refs.form as Vue
      }
    }
    

    The v-form instance has a validate method that returns a boolean, so we need to use an intersection type literal:

    computed: {
      form(): Vue & { validate: () => boolean } {
        return this.$refs.form as Vue & { validate: () => boolean }
      }
    }
    

    Then we can use it like so: this.form.validate()


    A better solution would be to create a type with the intersection so that it can be reused across multiple components.

    export type VForm = Vue & { validate: () => boolean }
    

    Then import it in the component:

    computed: {
      form(): VForm {
        return this.$refs.form as VForm
      }
    }
    
    0 讨论(0)
提交回复
热议问题