13

My goal is to define my rules once and then reuse them for all of my fields. To do this, I need to pass extra parameters to my rules, like maxlength of 20 on one v-text-field, but a maxlength of 50 on another. From what I see, only the value is getting passed. How can I add extra parameters to my rules?

<template>
  <v-input :rules=[rules.max(20)] v-model="field1" />
  <v-input :rules=[rules.max(50)] v-model="field2" />
</template>
<script>    
  data() {
    rules: {
      max(v, maxnum) { //maxnum is the parameter I want to add so that I can pass different values and reuse the same rule on multiple fields
        return (v || '').length <= maxnum || 'Max exceeded';
      }
    }
  }
</script>

4 Answers4

20

You need a function that returns the rule function. The wrapper function should accept any extra params that the rules function doesn't know about (anything other than the value):

<template>
  <v-input :rules=[rules.max(20)] v-model="field1" />
  <v-input :rules=[rules.max(50)] v-model="field2" />
</template>

<script>    
  data() {
    rules: {
      max(maxNum) {
        return v => (v || '').length <= maxNum || 'Max exceeded';
      }
    }
  }
</script>
Chase DeAnda
  • 15,963
  • 3
  • 30
  • 41
3

just pass v-model variable as second parameter to your rule.

<template>
  <v-input :rules=[rules.max(20, field1)] v-model="field1" />
  <v-input :rules=[rules.max(50, field1)] v-model="field2" />
</template>

<script>    
  data() {
    rules: {
      max(maxnum, v) { 
        return (v || '').length <= maxnum || 'Max exceeded';
      }
    }
  }
</script>
mostafaznv
  • 958
  • 14
  • 24
1

Quasar example

The rules property expects an array. This is one of the correct ways to do it:

<template>
  <!-- ... -->
  <q-input
     v-model="username"
     label="Username"
     :rules="maxRule(30)"
     />
  <!-- ... -->
</template>

<script>
import { ref } from 'vue'
export default {
  setup (props) {
    const username = ref(null)
    const maxRule = (limit) => [val => val.length <= limit || `Please use maximum ${limit} characters`]
    return {
      username,
      maxRule 
    }
  }
}
</script>
fromani
  • 181
  • 1
  • 3
1

This is easily implemented by resorting to a high-order-function:

<template>
  <v-input :rules=[rules.max(20)] v-model="field1" />
  <v-input :rules=[rules.max(50)] v-model="field2" />
</template>
<script>    
  data() {
    rules: {
      max: (maxnum) => (value) => {
        return (v || '').length <= maxnum || 'Max exceeded'
      }
    }
  }
</script>

Like this rules.max(5) returns (value) => return (v || '').length <= 5 || 'Max exceeded'

Pedro Rolo
  • 28,273
  • 12
  • 60
  • 94
  • This is much cleaner. With typescript though, whats the highest order functions type? – Second2None Aug 30 '23 at 00:25
  • 1
    it's a function that gets a number and returns a function that gets an number and returns a validation result. I suppose that the validation result is boolean | string – Pedro Rolo Aug 31 '23 at 13:20
  • I ended up creating a custom type that allowed multiple parameters. Not sure if this is correct but its working. `export type ValidationFunction = ( s: T, b?:T, d?:T ) => (c: T) => boolean | string` – Second2None Aug 31 '23 at 13:23
  • // I guess this type Validation = (value: string) => string | boolean; (maxnum:number): Validation => (value:string) => { return (v || '').length <= maxnum || 'Max exceeded' } – Pedro Rolo Aug 31 '23 at 13:44