Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples/documentation for using vuelidate with TypeScript #175

Open
jawnsy opened this issue Aug 24, 2017 · 72 comments
Open

Examples/documentation for using vuelidate with TypeScript #175

jawnsy opened this issue Aug 24, 2017 · 72 comments
Labels
Projects

Comments

@jawnsy
Copy link

jawnsy commented Aug 24, 2017

Hello!

First off, thank you to the Vuelidate creators for making this amazing little validation library. Second, thank you to @mrellipse for contributing type definitions in #47.

I have been trying to figure out how to use Vuelidate with TypeScript from the PR history, by perusing the PR code, and by just generally futzing around. I see that the changes should extend the Vue interface declaration with enough information to know that the validations field is an available option.

However, I can't for the life of me figure out what I need to do to make this all play nicely. I tried using the @Component syntax from the tests (component.spec.ts) but get this error:

ERROR in [...]\src\calculator\Calculator.vue.ts
(96,5): error TS2345: Argument of type '{ mixins: any[]; name: string; template: string; validations: any; }' is not assignable to parameter of type 'VueClass'.
Object literal may only specify known properties, and 'mixins' does not exist in type 'VueClass'.

corresponding to this code (mostly borrowed from the test file, and embedded in a .vue single file component):

<script lang="ts">

import Vue = require('vue');
import Component from 'vue-class-component';
import { IVuelidate, ValidationRuleset, Vuelidate, validationMixin } from 'vuelidate';

interface IComplexProp {
    value1: string;
    value2?: number;
}

type SimpleProp = string;

interface IComponentData {
    simpleProp: SimpleProp;
    complexProp: IComplexProp;
    simpleCollection: Array<SimpleProp>;
    complexCollection: Array<IComplexProp>;
    validationGroup: string[];
};

function predicate(value: any): boolean {
    return value ? true : false;
}

function predicateFactory(param: number): (value: any) => boolean {
    return (value) => predicate(value);
}

let validations: ValidationRuleset<IComponentData> = {
    simpleProp: {
        predicate
    },
    complexProp: {
        value1: {
            predicate,
            funcGen: predicateFactory(1)
        },
        value2: {
            predicate,
            funcGen: predicateFactory(1)
        }
    },
    simpleCollection: {
        $each: {
            predicate
        }
    },
    complexCollection: {
        $each: {
            value1: {
                predicate,
                funcGen: predicateFactory(1)
            }
        }
    },
    validationGroup: ['simpleProp', 'complexProp.value2']
};

@Component({
    mixins: [validationMixin],
    name: 'RulesetTest',
    template: '<div></div>',
    validations: validations
})
class TestComponent extends Vue implements IVuelidate<IComponentData> {

    constructor() {
        super();
    }

    simpleProp: string = 'true';

    complexProp: IComplexProp = {
        value1: '',
        value2: 1
    }

    simpleCollection: SimpleProp[] = ['A', 'B', 'C'];

    complexCollection: IComplexProp[] = [
        { value1: 'A' },
        { value1: 'B' },
        { value1: 'C' }
    ];

    simpleMethod(): boolean {
        return this.$v.complexProp.$dirty;
    }

    $v: Vuelidate<IComponentData>
}

</script>

Is there a guide for how to use Vuelidate with Vue Single File Components written in TypeScript? I've been trying to piece it together from the documentation embedded with the .ts code, but as I'm new to TypeScript and ES6, this has been a bit of a challenge for me.

@Frizi
Copy link
Contributor

Frizi commented Aug 24, 2017

I personally never used it with typescript, and if You @jawnsy are able to figure that out, I'd be very happy to add that as official guide. Alongside type definitions contributed by @mrellipse. I'm personally using flowtype in my project and it's terrible enough in vue files that i'm mostly typing things outside of vue components.

@mrellipse
Copy link

mrellipse commented Aug 26, 2017 via email

@OvidiuBan
Copy link

Would be amazing to see a simple component typescript validation with vuelidate. Just a simple required or custom validaton ( let's say odd number ) added on a property in the component & not html.
Could you add an example with that? @jawnsy @mrellipse ?

@Frizi
Copy link
Contributor

Frizi commented Aug 31, 2017

I'm finally playing with TypeScript with Vue on my own right now. With intention to eventually be able to develop those definitions and support them with confidence.

Still, contributions highly appreciated 😉

@mmajcenic
Copy link

@mrellipse Thank you for providing typescript definitions for vuelidate! If I may ask, how can I define custom validator with params?

@mrellipse
Copy link

It's great to see vuelidate has got so much traction in the vue community!

Just to clarify. The pull request I made to include typescript definitions never ended up being merged. And given my work and other ambitions at the moment, I couldn't commit to maintaining them. 😞

If someone wants to take it to use as an ongoing contribution, you have my 👍

@OvidiuBan, here is a screenshot. It shows suggestions on a component property based on vuelidate.d.ts

vuelidate d ts

@mrellipse
Copy link

Hi @mmajcenic if you have a look at the above screenshot, and then check out signup.ts if should put you on the right track to defining a custom validation.

@Frizi
Copy link
Contributor

Frizi commented Sep 3, 2017

@mrellipse This looks amazing 😍 I wanted to reopen your PR but was unable to do so, as your repository got deleted. I'm definitely going to merge that though, especially now after playing a bit with typescript and understanding it a bit better. Ideally i'd like You to reopen it if possible.

@victorgarciaesgi
Copy link
Contributor

@mrellipse how did you do to have the suggestions?
I got this error when I call this.$v
error TS2339: Property '$v' does not exist on type

I put vualidate.d.ts in src/typings, but typescript and webpack don't seem to read it...

@victorgarciaesgi
Copy link
Contributor

@mrellipse BTW i'm on VScode with Typescript 2.5.3 and Webpack 3.6.0

@John0x
Copy link

John0x commented Nov 9, 2017

What is the status of this?
Is Vuelidate usable with typescript?

@brianjorden
Copy link

Well after looking at several potential validation packages, I decided this is what I wanted to go with before I realized there would be some challenges with Typescript and Vue Class Components. I'm not sure, but I'm guessing it might be at least a LITTLE smoother if you aren't using classes and just doing the newer Vue.extend type approach (still missing too many TS benefits for me personally).

After some fighting with it and looking at how vuelidate, vue-class-component, vue-property-decorator, and a few other things kinda work under the hood I had some success here. I ended up getting a partial version up and running even with basically all of the super strict settings in Typescript after leveraging/adapting a big chunk of the typings @mrellipse already wrote.

This is pretty hacky and incomplete, but if others are really looking to use this with Typescript I'll try to find some time to finish out a more friendly version and open a PR. Oh and I've only attempted to deal with using this as a mixin, and hopefully obviously this is tested for all of a few minutes so far, but stepping away for a bit and thought I'd share first.

Vue Class Component Usage:

<script lang="ts">
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import { validationMixin } from 'vuelidate'
import { required, minLength } from 'vuelidate/lib/validators'

@Component({
  mixins: [validationMixin],
  validations: {
    something: { required, minLength: minLength(4) },
  },
})
export default class Dashboard extends Vue {
  something: string = ''
...

Type Definitions: vuelidate.d.ts

declare module 'vuelidate' {
  // we need to augment the actual Vue types
  import vue from 'vue'

  // must bolt on the validations property to the input of ComponentOptions
  // and also onto the "output" of @Component in the form of VueClass<Vue>
  module 'vue/types/options' {
    interface ComponentOptions<V extends vue> {
      validations?: { [x: string]: any }
    }
    interface VueClass<V extends vue> {
      validations?: { [x: string]: any }
    }
  }

  // handles making this.$v work within a component context, but it isn't typed
  // at all right now. still need to look in depth at @mrellipse's version
  module 'vue/types/vue' {
    interface Vue {
      $v?: { [x: string]: any }
    }
  }

  // definitions of what vuelidate exports help keep typescript from yelling
  export const validationMixin: {
    data: () => { [x: string]: any }
    beforeCreate: () => void
    beforeDestroy: () => void
  }

  // untested
  export function withParams(
    paramsOrClosure: any,
    maybeValidator: any,
  ): (...args: any[]) => any

  // these are untested, the Vue.use approach to make it a global mixin
  export function Vuelidate(Vue: vue): void
  export default function(Vue: vue): void
}

// the individual validators to import
declare module 'vuelidate/lib/validators' {
  /** Accepts only alphabet characters. */
  function alpha(value: any): boolean
  /** Accepts only alphanumerics. */
  function alphaNum(value: any): boolean
  /** Checks if a number is in specified bounds. Min and max are both inclusive. */
  function between(min: number, max: number): (value: any) => boolean
  /** Accepts valid email addresses. Keep in mind you still have to carefully verify it on your server, as it is impossible to tell if the address is real without sending verification email. */
  function email(value: any): boolean
  /** Requires the input to have a maximum specified length, inclusive. Works with arrays. */
  function maxLength(max: number): (value: any) => boolean
  /** Requires the input to have a minimum specified length, inclusive. Works with arrays. */
  function minLength(min: number): (value: any) => boolean
  /** Requires non-empty data. Checks for empty arrays and strings containing only whitespaces. */
  function required(value: any): boolean
  /** Checks for equality with a given property. Locator might be either a sibling property name or a function, that will get your component as this and nested model which sibling properties under second parameter. */
  function sameAs(locator: string): (value: any, vm?: any) => boolean

  // stripped these down to just any[] to keep this first attempt simple
  /** Passes when at least one of provided validators passes. */
  function or(...validators: any[]): () => boolean
  /** Passes when all of provided validators passes. */
  function and(...validators: any[]): () => boolean

  // new validators since @mrellipse's version, need comments/verification of params/types
  function numeric(value: any): boolean
  function ipAddress(value: any): boolean
  function macAddress(separator?: string): (value: any) => boolean
  function requiredIf(locator: string): (value: any, vm?: any) => boolean
  function requiredUnless(locator: string): (value: any, vm?: any) => boolean
  function url(value: any): boolean
  function minValue(min: number): (value: any) => boolean
  function maxValue(max: number): (value: any) => boolean
}

@bponghneng
Copy link

@brianjorden Thanks for your work! I'm familiar with TypeScript, but I wouldn't call myself a wizard. However, looking over your defs, it should solve the errors I'm getting via tslint--but tslint obviously isn't recognizing the vuelidate.d.ts file I created at the root of my src tree. Basically, same issue as @victorgarciaesgi above (though I'm using PHPStorm and Webpack). Can you make a quick note where to store the vuelidate.d.ts file and how to config tslint to see it correctly?

@brianjorden
Copy link

brianjorden commented Nov 14, 2017

@bpongvh inclusion of the type file depends mostly on your tsconfig.json, mind sharing your current settings? Depending on your config, you may be able to throw it anywhere under your src or app directory as is my case. My tsconfig.json has this (my main directory is app not src): "include": ["./app/**/*"], but I have noticed when ever I create a new file VS Code doesn't pick it up until I close/reopen it. If you have anything specified for types or typeRoots under compilerOptions things might get a bit funky. At the time I posted that prior message, the file was at the root of my source directory (app), but I've since moved it to a types directory under my app directory.

A consideration though, my current project setup is actually an extremely opinionated configuration to simplify a bunch of stuff for me, but isn't really meant for general usage. For example, I have several things globally declared, if I'm importing Vue into every file, do I really need to type that out every time? So I've tried to setup that example in a more general usage friendly manner.

If your error is when referencing the this.$v object, it sounds as though the mixin isn't finding your validations definition. The vuelidate package currently only ever attaches $v to components that have a validations block defined. If/when I do a pull request for Typescript definitions, I was also considering a separate suggestion of bolting on an empty $v = {} placeholder if it is installed globally.

Could you provide a simple example of your component definition, validations block, and how you are importing/including the mixin (globally or locally)? Also what version of Vue and Typescript?

@victorgarciaesgi
Copy link
Contributor

I'm using it with Typescript and I had to modify the typings a little bit! you can see it on one of my components but it works great!!

link to repo

(In my exemple I pass respective $v field to each input components to have independent errors logic)

Basicaly declare it as a IValidator to have suggestions in Vscode

@Prop({required: false}) $v: IValidator;

@brianjorden
Copy link

@victorgarciaesgi completely off topic, but I was just glancing at your repo and think I see a bug. Your error messages have some references to a typo as the word Lenght (few instances of that)

@victorgarciaesgi
Copy link
Contributor

@brianjorden Hey yeah thanks I forgot I had this error and I thought I fixed it! That's just the beginning of a student project so this is not the main focus :)

@victorgarciaesgi
Copy link
Contributor

@brianjorden Ok I had just mispelled "Length" with "Lenght", so frustrating aha

@bponghneng
Copy link

@brianjorden @victorgarciaesgi Thanks for the notes! Got my setup to read the types now. I guess I had some other strange problem that was choking the ts compiler. Anyway, all works with whats defined in the types file. One note, however: I'm getting tslint complaints about $el not defined on Vue when I try to use Vuelidate as a global: "Property '$el' is missing in type 'VueConstructor.'" I studied the problem for a while, and I think it has to do with ...

// these are untested, the Vue.use approach to make it a global mixin
  export function Vuelidate(Vue: vue): void
  export default function(Vue: vue): void

My guess is it has to do with param types--maybe should be VueConstructor<Vue> to get the Vue interface to merge correctly. However, sorting all that out seems beyond me at the moment :) I ended up just using the mixin approach for now. Interested for updates to make the Vue.use approach work out.

@ozeebee
Copy link

ozeebee commented Nov 28, 2017

Hi guys, I had to give up using the abovementionned solution(s) after upgrading to TypeScript 2.6 and Vue 2.5+.
Nevertheless, I found declarations in this project to be helpful in my case.

@Frizi
Copy link
Contributor

Frizi commented Dec 10, 2017

@ozeebee It is inaccurate in a way that validator may just be any function that return boolean or promise. Nice that it's working for you guys and i'm going to soon roll out the typings into official package.

@TheDeveloperTom
Copy link

@Frizi so how soon will you roll out the official typings? :)

@ozguruysal
Copy link

Looking forward to official typescript support!

@kirillgroshkov
Copy link

typings?

@jgauffin
Copy link

Typings for the people ;)

@pranavjindal999
Copy link

So when are we getting TS update? looking forward to it....

@IMAMBAKS
Copy link

IMAMBAKS commented Apr 4, 2018

I'm also looking for forward to the TS update.

janesser added a commit to janesser/vuelidate that referenced this issue May 12, 2018
@janesser
Copy link

PR on #287. Comments welcome.

@wujekbogdan
Copy link

Is there any way to get around TypeScript compilation failure when calling this.$v.$reset() and this.$v.$touch() methods? I'm getting the following error:

Cannot invoke an object which is possibly 'undefined'.

The only solution I found so far is to wrap $reset() and $touch() method calls in if statements.

if (this.$v) {
  this.$v.$touch()
}

PS
@janesser thanks a lot for your typings declarations!

@maciz84
Copy link

maciz84 commented Sep 14, 2018

That’s the only way as far I know to get around that ‘issue’

Rouche added a commit to Rouche/vuelidate that referenced this issue Oct 19, 2018
@maciek134
Copy link

@wujekbogdan another solution, if you are sure $v exists on this you can do this.$v!.touch()

@Chris2011
Copy link

I handled it with the example from the ticket creator. I moved my validations object out of the component class and added it into the @component decorator. After this, this.$v got defined. But it feels not correct.

@ArtemKha
Copy link

It should work fine after installing:

npm i @types/vuelidate --save-dev

also you could try to delete node_modules dir and .lock file and ran npm install

@jacek-jablonski
Copy link

Hi,
as @Chris2011 mentioned putting validations into @component doesn't feel right :)
Is there any other possibility to put it inside class?

@janesser
Copy link

@Chris2011 @jacek-jablonski

Be aware that the annotation is taken to "decorate" the validation() method into the component. To my knowledge, if you want to skip the annotation decorator thing, nothing is hindering you, though the typing won't be on your side.

@jacek-jablonski
Copy link

@janesser but when I move validation: {...} part from annotation decorator directly to class, I get error saying that $v is referenced during rendering but it's not defined. So it seems it is not something we can choose.

@victorgarciaesgi
Copy link
Contributor

@jacek-jablonski
With vue-property-decorator you can use the method registerHooks to do that

In your main.ts

import { Component } from 'vue-property-decorator'

Component.registerHooks(['validations'])

Then on your components

import { Component, Vue } from 'vue-property-decorator';

@Component
export default class Blank extends Vue {
    validations() {
       return {
        ...
       }
    }
  }
}

@jacek-jablonski
Copy link

@victorgarciaesgi Thank you!

@Chris2011
Copy link

@victorgarciaesgi thx, will do :)

@jacek-jablonski
Copy link

@victorgarciaesgi I still have trouble implementing it the way you showed. When looking through Vue.js devtools $v property is not present. But when I make some small change, that causes Vue to reload, it suddenly appears in computed properties.

@Chris2011
Copy link

After updating dependencies in my package.json, I got the error: Property '$v' does not exist on type 'Login' while Login is my component. After this, I tried what @victorgarciaesgi said but still the same.

@Chris2011
Copy link

Before updating everything worked fine for me. Came back from vacation, should go to vacation again :D.

@Chris2011
Copy link

Ok, it was a problem via npm install. After using yarn install on the vue cli, everything works fine. :)

@ktiedt
Copy link

ktiedt commented Aug 9, 2019

I am also having trouble getting Vuelidate to play nicely with Typescript -- I've followed multiple examples from various tickets or comments here including the nuxted based vue playground project and they all end up erroring with something like.

ERROR ERROR in /Users/ktiedt/Projects/nuxt-dartmud/pages/register.vue 18:00:54
64:31 Property 'required' does not exist on type 'NonNullable<Validation & ValidationProperties<this["accountRealName"]>>'.
62 | const errors: string[] = []
63 | if (!this.$v.accountRealName!.$dirty) return errors

64 | !this.$v.accountRealName!.required && errors.push('Your real name is required')
| ^
65 | return errors
66 | }
67 |

ERROR ERROR in /Users/ktiedt/Projects/nuxt-dartmud/pages/register.vue 18:00:54
71:28 Property 'maxLength' does not exist on type 'NonNullable<Validation & ValidationProperties<this["accountName"]>>'.
69 | const errors: string[] = []
70 | if (!this.$v!.accountName!.$dirty) return errors

71 | !this.$v!.accountName!.maxLength && errors.push('Character name must be at most 11 characters long')
| ^
72 | !this.$v!.accountName!.required && errors.push('Character name is required.')
73 | return errors
74 | }

My component looks like this currently.

<template>
  <v-layout class="register">
    <v-flex>
      <v-card>
        <v-card-title>Register an account</v-card-title>
        <v-card-text>
          <form>
            <v-text-field
              v-model="accountRealName"
              :error-messages="realNameErrors"
              label="Real name"
              required
              @input="$v.accountRealName.$touch()"
              @blur="$v.accountRealName.$touch()"
            ></v-text-field>
            <v-text-field
              v-model="accountEmail"
              :error-messages="emailErrors"
              label="E-mail"
              required
              @input="$v.accountEmail.$touch()"
              @blur="$v.accountEmail.$touch()"
            ></v-text-field>
            <v-text-field
              v-model="accountName"
              :error-messages="nameErrors"
              :counter="10"
              label="Character name"
              required
              @input="$v.accountName.$touch()"
              @blur="$v.accountName.$touch()"
            ></v-text-field>
            <v-btn class="mr-4" @click="submit">submit</v-btn>
            <v-btn @click="clear">clear</v-btn>
          </form>
        </v-card-text>
      </v-card>
    </v-flex>
  </v-layout>
</template>

<script lang="ts">
import { validationMixin } from 'vuelidate';
import { required, maxLength, email, ValidationRule } from 'vuelidate/lib/validators'
import { Component, Vue } from 'nuxt-property-decorator'
import { ValidationProperties } from 'vue/types/vue';

@Component({
  mixins: [validationMixin],
  validations: {
    accountName: { required, maxLength: maxLength(11) },
    accountEmail: { required, email },
    accountRealName: { required }
  }
})
class Register extends Vue {
  accountName: string = ''
  accountEmail: string = ''
  accountRealName: string = ''

  get realNameErrors () {
    const errors: string[] = []
    if (!this.$v.accountRealName!.$dirty) return errors
    !this.$v.accountRealName!.required && errors.push('Your real name is required')
    return errors
  }
  
  get nameErrors () {
    const errors: string[] = []
    if (!this.$v!.accountName!.$dirty) return errors
    !this.$v!.accountName!.maxLength && errors.push('Character name must be at most 11 characters long')
    !this.$v!.accountName!.required && errors.push('Character name is required.')
    return errors
  }

  get emailErrors () {
    const errors: string[] = []
    if (!this.$v.accountEmail!.$dirty) return errors
    !this.$v.accountEmail!.email && errors.push('Must be valid e-mail')
    !this.$v.accountEmail!.required && errors.push('E-mail is required')
    return errors
  }
}

export default Register
</script>

<style lang="scss" scoped>
.register {
  color: inherit;
}
</style>

@jacek-jablonski
Copy link

jacek-jablonski commented Aug 13, 2019

@victorgarciaesgi Hi,
do you have any idea why it might not work with yours provided suggestion? I have registered hook (validations), but it still behaves as I described earlier: right after refreshing, no $v object is present, but small change in code triggers hot-reload and right after that $v suddenly appears.

EDIT: ok, I managed to solve my issue. It seems that it is important to register Component hooks in external file. After that, it just works.

@Chris2011
Copy link

Hey @jacek-jablonski can you please share your environment please? If possible :)

@jacek-jablonski
Copy link

jacek-jablonski commented Aug 13, 2019

@Chris2011 of course, here it is:

// registerComponentHooks.ts
import { Component } from "vue-property-decorator"

Component.registerHooks(["validations"])
// main.ts
import Vue from "vue"
import Vuelidate from "vuelidate"
import "./registerComponentHooks"

Vue.use(Vuelidate)
// ...

and sample component:

<template>
  <b-form>
    <b-form-group>
      <label form="diplay-name">Diplay name</label>
      <b-form-input id="display-name" v-model.trim="$v.modifiedAccount.displayName.$model" type="text"></b-form-input>
    </b-form-group>
  </b-form>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"
import { required } from "vuelidate/lib/validators"
import { Account, AccountModify } from "@/store/modules/accounts/models"

@Component
export default class AccountModifyForm extends Vue {
  @Prop() readonly account: Account

  private modifiedAccount: AccountModify = null

  created() {
    this.modifiedAccount = {
      displayName: this.account.displayName,
      email: this.account.email
    }
  }

  validations() {
    return {
      modifiedAccount: {
        displayName: { required }
      }
    }
  }
}
</script>

@rodolphocastro
Copy link

Just to add another example of using Single File Components, Typescript and Vuelidate togheter:

<script lang='ts'>
import Vue from 'vue'
import { required, email, ValidationParams, ValidationRule } from 'vuelidate/lib/validators'
import Component from 'vue-class-component'

@Component({
  name: 'ajuda',
  validations: {
    userEmail: {
      required,
      email
    },
    userMessage: {
      required
    }
  }
})
export default class Ajuda extends Vue {
  userEmail = ''
  userMessage = ''

submitDataDummy () {
    this.$v.$touch()
    if (this.$v.$invalid) {
      this.$swal({
        titleText: 'Dados Incorretos',
        text: 'Sua mensagem não foi enviada',
        icon: 'error',
        toast: true,
        position: 'bottom',
        timer: 5000,
        timerProgressBar: true
      })
    } else {
      this.$swal({
        titleText: 'Obrigado',
        text: 'Obrigado por entrar em contato conosco!',
        icon: 'success'
      })
    }
  }
}

@CodeSteele
Copy link

Weird change, haven't been able to nail it down yet: if I define it as a property on the object component, it works fine, if I use the validations() method it does not, we recently moved from webpack to using Vue CLI (which is... still just webpack), trying to find out what I'm missing. Still registering the component hook.

@CodeSteele
Copy link

Putting this:

Component.registerHooks(["validations"]);

In my SFCs fixed it, not really sure why I suddenly need to do this there too, but when I move to a full SPA this will probably go away.

@FloryanFilip
Copy link

FloryanFilip commented Apr 8, 2020

To add on the topic, I was experiencing the same Issue that @jacek-jablonski had, on page refresh $v wouldn't exist at all, but after any small code change a hot-reload would fire and $v object would appear.
The solution for me was identical to @jacek-jablonski but I had to put import statement in main.ts at the top of the file.

// main.ts

import './registerComponentHooks.ts'; <-- this has to be first import

import Vue from 'vue';
...

@irhamputra
Copy link

I have the validation structure like this

validations() {
  people: {
      required,
      $each: {
         name: minLength(3)
      }
  }
}

my achievement is, I just want to get any auto completion in $v.people.$model in my template.

how do I do that?
I just saw the old one from above and I have tried working around in both ways @Ref() $v!: Vuelidate<MyInterface> and v!: Vuelidate<MyInterface> and I get an error. is the only way is to do NonNullable type like $v!.people!.$model?

@FloryanFilip
Copy link

@irhamputra Can you provide the error you get and template part?
$v!.people!.$model is a hacky way unless you are certain it will ALWAYS be there, instead perhaps try something like $v && $v.people && $v.people.model

@irhamputra
Copy link

irhamputra commented Jun 10, 2020

Hi @FloryanFilip for replying. Actually I don't get any error in template, but in the script because Vuelidate instance from vuelidate module is not in the module and I just don't get the auto completion. What I want to achieve that I can get the reference type for this.$v e.g this.$v.people.§model or any types. But I console.log this.$v, I get the object for .people.$model so maybe I just think this type is always NonNullable and I don't do $v && $v.people && $v.people.model

@foxCliff
Copy link

foxCliff commented Feb 3, 2022

I ran into a problem
From example "Custom error messages"
`import { required, helpers, minLength } from '@vuelidate/validators'

const validations = {
name: {
minLength: helpers.withMessage(
({
$pending,
$invalid,
$params,
$model
}) => This field has a value of '${$model}' but must have a min length of ${$params.min} so it is ${$invalid ? 'invalid' : 'valid'},
minLength(4)
)
}
}`

Typescript swears at min property of object $param: "Property 'min' does not exist on type 'object'."

Has anyone else experienced this and knows how to fix this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Vuelidate
  
To do
Development

No branches or pull requests