Reuse of validation rules



  • I really like the fact that validations are now handled directly by the Quasar framework and not by an external package. They are also straightforward to define, including the error messages when the validation fails. But (as far as I can tell) using the same validation rules in more than one form requires repeating the code. Here is an example of what I expected I can do:

    1. Have a validations.js file with the list of rules to be used throughout my project
    const emailPattern = /^(?=[a-zA-Z0-9@._%+-]{6,254}$)[a-zA-Z0-9._%+-]{1,64}@(?:[a-zA-Z0-9-]{1,63}\.){1,8}[a-zA-Z]{2,63}$/;
    
    export const email = val => emailPattern.test(val) || 'Please enter a valid email address';
    export const required = val => !!val || 'Field is required';
    
    1. Use the rules in validations.js wherever validation is required. For example a login form would look something like:
    <template>
      <div style="width: 500px; max-width: 90vw;">
        <q-input
          v-model="form.userName"
          label="User"
          :rules="[required, email]" />
        <q-input
          v-model="form.password"
          type="password" label="Password"
          @keyup.enter="loginClick"
          :rules="[required]" />
        <div class="row" style="display: flex;align-items: center;">
          <div class="col-4">
            <small>
              Not registered?
              <span @click="openUserRegistration()">Register now</span>
            </small>
          </div>
          <div class="col-6"></div>
          <div class="col-2">
            <q-btn rounded color="primary" label="Login" @click="loginClick" />
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import { required, email } from '../validations';
    
    export default {
    ......................
    }
    </script>
    

    When I try running this code, eslint gives me a no-unused-vars on the import line as if the required and email are not used anywhere, but they are clearly used in the :rules attributes on the q-input tags. If I disable the eslint error for that line, the code runs, but no validation occurs. For example I can have an invalid e-mail address in the User field, and no error will be shown. Or I can have empty user and password and no error will be shown.

    The only way I could make the validations work is to either define the functions directly in the :rules attribute, which is really ugly and impractical, or I can define methods in the component like:

      methods: {
        // validations
        required(val) {
          return required(val);
        },
        email(val) {
          return email(val);
        },
        // end validations
    .......................
      },
    

    and change the :rules attribute in the template to be:

          :rules="[this.required, this.email]"
    

    While I like this second approach better than defining the functions directly in the attribute, it still defies the principle of re-usability.

    My questions are: why is my first approach not working and how can I have reusable validation rules?



  • If you don’t have your methods, props, computeds, etc. inside the component’s options object (the code inside export default{}), then the component’s template has no knowledge of or rather can’t access those things. Just importing the methods does nothing and eslint is right for saying they aren’t used.

    Also, this isn’t needed inside of the template. You only need [required, email].

    Lastly, if you just do this,

    methods: {
      email, 
      required
    }
    

    you have successfully added your imported methods into the component.

    https://codesandbox.io/s/codesandbox-app-fs1hy

    Scott



  • Scott, thank you for the example. It is indeed a lot more compact than what I had. It’s almost as good as what I wanted and I already modified my code to match it. My concern is that as concise as this is, it still requires me to mention the validation rules twice, once in the import and once in the methods. I can easily see compilation errors in my future, when I forget to add a rule in one of the two places where I have to have it or delete it from one of the two places it is.

    I guess my question then is to the Quasar team: could a babel plugin be written to automatically generate the

    methods: {
       email,
       required,
    }
    

    when the code is compiled, and include the plugin with the Quasar framework?



  • you can make a boot file and register your methods as a vue prototype, if youre concern about importing and whatnot, then in your component call it this.$myValHelper.required(someval) in script part of your sfc and without this in the template.
    I dunno why you are so concern with compile errors, in your trivial case a good ide would already warn you about error and won’t let you compile.



  • I don’t get the concern either. The import and declaration in methods is one way. Globally binding the methods to Vue through a boot file is another.

    Put it this way. If you imported the functions in any other code anywhere else, you’d have to also “use” them (i.e. write them out) somewhere in your JS code too.

    Something else you can try is to construct/ design your own custom input component with whatever validation you need and “reuse” your custom component, where you need it. For instance a <my-email-input> component.

    Scott


Log in to reply