vuelidate multiple error-labels



  • If I have an input that I have validated using several rules like this:
    password: { required, minLength(5), maxLength(8) }

    And I have this q-field with q-input:

      <q-field class="q-mb-md"
                 icon="lock"
                 :label='$t("passwordLabel")'
                 :error="$v.user.password.$error"
                 :error-label='...'
                 count>
          <q-input type="password"
                   v-model="user.password"
                   @blur="$v.user.password.$touch" />
        </q-field>
    

    Pay attention to :error-label='...'. How would I display a different message according to the rule that is wrong? I could think of a way (look below), but If I have many inputs I would be repeating myself a lot. Is there a better technique to solve this, like associate an error-label to a rule or something?

    :error-label='
    if ($v.user.password.required) 
       "Required field"
    else if ($v.user.password.minLength)
        "Minimum length is ${$v.user.password.$params.minLength.min}"
    else if ($v.user.password.maxLength)
        "Maximum length is ${$v.user.password.$params.maxLength.max}"
    


  • haven’t tried it, but maybe you can take a look at this https://dobromir-hristov.github.io/vuelidate-error-extractor/other_frameworks.html#usage-with-quasar.

    using a model for the error-label (not using the above link):

     <q-field class="q-mb-md"
      icon="lock"
      :label='$t("passwordLabel")'
      :error="$v.user.password.$error"
      :error-label="errMsgs.password"
      count>
        <q-input type="password"
           v-model="user.password"
           @blur="checkErr($v.user.password), 'password'" />
    </q-field>
    
    data () {
      errMsgs: {
        password: ''
      },
      user: {
        password: ''
      }
    },
    methods: {
      checkErr (val, name) {
        val.$touch()
        if (!val.required) {
          this.errMsgs[name] = 'Field is required.'    
        }
        if (val.hasOwnProperty('maxLength') && !val.maxLength) {
          this.errMsgs[name] = 'Max length is ' + val.$params.maxLength.max
        }
        if (val.hasOwnProperty('minLength') && !val.minLength) {
          this.errMsgs[name] = 'Min length is ' + val.$params.minLength.min
        }
      }
    },
    validations () {...}
    

    the solution require one error label message holder each field, ie. for username etc… on your submit you can iterate through $v.[whatever nested object you added in validations in here] and pass that to checkErr() function to check everything. I hope this helps a bit.

    using the link:
    https://codesandbox.io/s/q8pzo4q6kq

    this solution will need a bit of setup in your actual project, ie. adding Vuelidate-error-extractor as plugin, and creating the components to get you running with it.



  • This post is deleted!


  • @metalsadman I tried to implement the Vuelidate-error-extractor, but with no luck. Here are the steps I made

    1. npm install vuelidate-error-extractor
    2. added plugin ‘vuelidate-error-extractor’ using quasar CLI and added it to the “plugins” section in quasar.conf after Vuelidate:
     plugins: [
          'i18n',
          'axios',
          'vuelidate',
          'vuelidate-error-extractor'
        ]
    

    Here is the content of vuelidate-error-extractor.js:

    import VuelidateErrorExtractor, {templates} from 'vuelidate-error-extractor'
    import FormGroup from '../components/FormGroup.vue'
    import FormSummary from '../components/FormSummary.vue'
    
    const messages = {
      required: 'Field {attribute} is required',
      email: 'Field {attribute} is not a proper email address',
      maxLength: 'Field {attribute} exceeds maximum length.',
      minLength: 'Field {attribute} requires minimum length.'
    }
    
    export default ({app, router, Vue}) => {
      Vue.use(VuelidateErrorExtractor, {
        messages,
        attributes: {
          name: 'Name',
          email: 'Email',
          text: 'Text',
          username: 'Username',
          password: 'Password',
          firstName: 'First Name'
        }
      })
    
      Vue.component('FormGroup', FormGroup)
      Vue.component('FormSummary', FormSummary)
      Vue.component('formWrapper', templates.FormWrapper)
    }
    

    FormGroup and FormSummary are the same (copy-paste) as the ones provided in https://codesandbox.io/s/q8pzo4q6kq . I don’t even use FormSummary for now

    And here is my super simple RegisterForm

    <template>
        <form-wrapper :validator="$v.user">
            <form-group label="Email"
                        name="email">
                <q-input type="text"
                         v-model="user.email"
                         @blur="$v.user.email.$touch"/>
            </form-group>
        </form-wrapper>
    </template>
    <script>
    import { required, minLength, maxLength } from 'vuelidate/lib/validators'
    
    export default {
      data () {
        return {
          user: {
            email: ''
          }
        }
      },
      validations: {
        user: {
          email: { required, minLength: minLength(4), maxLength: maxLength(20) }
        }
      }
    }
    </script>
    

    But after I enter the page I don’t get the input displayed and I see these errors in the browser:

    [Vue warn]: Error in render: "TypeError: undefined is not an object (evaluating 'this.preferredValidator.$error')"
    
    found in
    
    ---> <FormGroup> at src/components/FormGroup.vue
           <FormWrapper>
             <Register> at src/pages/Register.vue
               <QPageContainer>
                 <QLayout>
                   <MyLayout> at src/layouts/MyLayout.vue
                     <App> at src/App.vue
                       <Root>
    TypeError: undefined is not an object (evaluating 'this.preferredValidator.$error')
    

    If I remove the form-wrapper like this the errors disappear.

    <template>
            <form-group :validator="$v.user.email" label="Email"
                        name="email">
                <q-input type="text"
                         v-model="user.email"
                         @blur="$v.user.email.$touch"/>
            </form-group>
    </template>
    

    but instead of the error message, below the input only ‘required’ or ‘minLength’ or ‘maxLength’ are displayed. In other words said, the keys are displayed, not the values (required: "Field {attribute} is required")

    P.S. In the first example with form-wrapper I found out that if I remove the name attribute from form-group the error dissapears, but things don’t work as expected.



  • yeah, didn’t also made it to work in my project (still need to dig in to this). kinda busy atm, so you can just do something like this:

    <q-field
      :error="$v.user.email.$error"
      :error-label="`${checkErr('E-mail', $v.user.email)}`">
        <q-input
           v-model="user.email"
           @blur="$v.user.email.$touch'" @input="$v.user.email.$touch'"/>
    </q-field>
    <q-field
      :error="$v.user.username.$error"
      :error-label="`${checkErr('Username', $v.user.username)}`">
        <q-input
           v-model="user.username"
           @blur="$v.user.username.$touch'" @input="$v.user.username.$touch'"/>
    </q-field>
    methods: {
      checkErr (fieldname, val) {
        if (!val.$error) {
          return ''
        }
        if (!val.required) {
          return `${fieldname} field is required.`
        }
        if (val.hasOwnProperty('maxLength') && !val.maxLength) {
          return `${fieldname} field exceeds max length of ${val.$params.maxLength.max}.`
        }
        if (val.hasOwnProperty('minLength') && !val.minLength) {
          return `${fieldname} field requires min length of ${val.$params.minLength.min}.`
        }
      }
    }
    

    tbh, you can make something like the Vuelidate-error-extractor with just vuelidate. make a custom component like a q-field wrapper same in the library’s example and pass $v.[formdata] as props to that component. $v object usually gives all that you need imo.



  • @reath From what I am seeing in the codesandbox you attached, it all works. Is there an issue with Quasal when using its CLI?



  • @dobromir Yes. The codesandbox link was provided by @metalsadman in order to guide me on how to use your extension. I’m using Quasar CLI and in the 1st topic I have posted the related code. Can you run the extension by plugging it in the Quasar CLI created project with i18n? Because I and @metalsadman can’t get it to work. Do you need more code?



  • I will look into it today. Didnt get notified for the reply. …



  • For some reason, Quasar is not loading my quasar.conf.js at all… I cannot setup the plugins.



  • @dobromir Try to reinstall Quasar-CLI. Then do a

    $ quasar init <folder-name>
    $ cd <folder-name>
    $ quasar dev
    

    I suggest enabling vuei18n in the init of the project because this way you’ll have a setup identical to mine.

    With this and the code I posted in https://forum.quasar-framework.org/post/10043 you’ll have a setup identical to mine



  • @reath - You forgot yarn install must be done too.

    Scott



  • @dobromir Another clue: yarn gives me this warning:
    vuelidate-error-extractor@2.2.2" has unmet peer dependency "vue@^2.5.16".



  • that is fine, it works fine with any vue 2.x version. I had an old CLI version along with the new one I just had installed. Going to try to do things now 😉



  • Found the issue. For some reason the bundled package for accessing deep object properties was returning undefined. Will fix it now and push a release.



  • OK, I was wrong. This is a Quasar CLI issue, rather then an issue with my plugin. Will make a PR to Quasar, see if it gets merged. Essentially you could try the not ESM build, so instead of what you had do this - import VuelidateErrorExtractor from 'vuelidate-error-extractor/dist/vuelidate-error-extractor'

    Problem comes from the fact. that there is a package, that uses an older version of a dependency the error extractor has. Because I do not bundle the deps in the ES module build, this happens. A properly configured webpack config should fix this 🙂



  • @reath I have made a PR to quasar cli that will fix the problem. Waiting on approval. Until then, tell me if the workaround above worked.

    PR for reference - https://github.com/quasarframework/quasar-cli/pull/198



  • This post is deleted!


  • @reath said in vuelidate multiple error-labels:

    but instead of the error message, below the input only ‘required’ or ‘minLength’ or ‘maxLength’ are displayed. In other words said, the keys are displayed, not the values (required: “Field {attribute} is required”)

    I have the same problem. key instead of values. Did you resolve this problem ?



  • A fix has been merged. Please update your Quasar CLI.