refactor: Validation callbacks logic simplification, typehints
This commit is contained in:
parent
99c3f8a4cd
commit
45f29ff27a
@ -36,11 +36,11 @@ class FileUpload {
|
|||||||
public context: ObjectType
|
public context: ObjectType
|
||||||
public results: any[] | boolean
|
public results: any[] | boolean
|
||||||
|
|
||||||
constructor (input: DataTransfer, context: ObjectType, options: ObjectType = {}) {
|
constructor (input: DataTransfer, context: ObjectType = {}, options: ObjectType = {}) {
|
||||||
this.input = input
|
this.input = input
|
||||||
this.fileList = input.files
|
this.fileList = input.files
|
||||||
this.files = []
|
this.files = []
|
||||||
this.options = { ...{ mimes: {} }, ...options }
|
this.options = { mimes: {}, ...options }
|
||||||
this.results = false
|
this.results = false
|
||||||
this.context = context
|
this.context = context
|
||||||
if (Array.isArray(this.fileList)) {
|
if (Array.isArray(this.fileList)) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { VueConstructor } from 'vue'
|
import { VueConstructor } from 'vue'
|
||||||
|
|
||||||
import library from './libs/library'
|
import library from './libs/library'
|
||||||
import rules from './libs/rules'
|
import rules from './validation/rules'
|
||||||
import mimes from './libs/mimes'
|
import mimes from './libs/mimes'
|
||||||
import FileUpload from './FileUpload'
|
import FileUpload from './FileUpload'
|
||||||
import RuleValidationMessages from './RuleValidationMessages'
|
import RuleValidationMessages from './RuleValidationMessages'
|
||||||
@ -13,7 +13,7 @@ import FormularioForm from '@/FormularioForm.vue'
|
|||||||
import FormularioInput from '@/FormularioInput.vue'
|
import FormularioInput from '@/FormularioInput.vue'
|
||||||
import FormularioGrouping from './FormularioGrouping.vue'
|
import FormularioGrouping from './FormularioGrouping.vue'
|
||||||
import { ObjectType } from '@/common.types'
|
import { ObjectType } from '@/common.types'
|
||||||
import { ValidationContext } from '@/validation.types'
|
import { ValidationContext } from '@/validation/types'
|
||||||
|
|
||||||
interface ErrorHandler {
|
interface ErrorHandler {
|
||||||
(error: any, formName?: string): any
|
(error: any, formName?: string): any
|
||||||
|
@ -25,7 +25,8 @@ import {
|
|||||||
Watch,
|
Watch,
|
||||||
} from 'vue-property-decorator'
|
} from 'vue-property-decorator'
|
||||||
import { shallowEqualObjects, parseRules, snakeToCamel, has, arrayify, groupBails } from './libs/utils'
|
import { shallowEqualObjects, parseRules, snakeToCamel, has, arrayify, groupBails } from './libs/utils'
|
||||||
import { ValidationError } from '@/validation.types'
|
import { ValidationError } from '@/validation/types'
|
||||||
|
import { ObjectType } from '@/common.types'
|
||||||
|
|
||||||
const ERROR_BEHAVIOR = {
|
const ERROR_BEHAVIOR = {
|
||||||
BLUR: 'blur',
|
BLUR: 'blur',
|
||||||
@ -87,12 +88,12 @@ export default class FormularioInput extends Vue {
|
|||||||
@Prop({
|
@Prop({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
}) validationRules!: Object
|
}) validationRules!: ObjectType
|
||||||
|
|
||||||
@Prop({
|
@Prop({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
}) validationMessages!: Object
|
}) validationMessages!: ObjectType
|
||||||
|
|
||||||
@Prop({
|
@Prop({
|
||||||
type: [Array, String, Boolean],
|
type: [Array, String, Boolean],
|
||||||
@ -112,16 +113,16 @@ export default class FormularioInput extends Vue {
|
|||||||
@Prop({ default: true }) preventWindowDrops!: boolean
|
@Prop({ default: true }) preventWindowDrops!: boolean
|
||||||
|
|
||||||
defaultId: string = this.$formulario.nextId(this)
|
defaultId: string = this.$formulario.nextId(this)
|
||||||
localAttributes: Object = {}
|
localAttributes: ObjectType = {}
|
||||||
localErrors: ValidationError[] = []
|
localErrors: ValidationError[] = []
|
||||||
proxy: Object = this.getInitialValue()
|
proxy: ObjectType = this.getInitialValue()
|
||||||
behavioralErrorVisibility: boolean = this.errorBehavior === 'live'
|
behavioralErrorVisibility: boolean = this.errorBehavior === 'live'
|
||||||
formShouldShowErrors: boolean = false
|
formShouldShowErrors: boolean = false
|
||||||
validationErrors: [] = []
|
validationErrors: [] = []
|
||||||
pendingValidation: Promise = Promise.resolve()
|
pendingValidation: Promise = Promise.resolve()
|
||||||
// These registries are used for injected messages registrants only (mostly internal).
|
// These registries are used for injected messages registrants only (mostly internal).
|
||||||
ruleRegistry: [] = []
|
ruleRegistry: [] = []
|
||||||
messageRegistry: Object = {}
|
messageRegistry: ObjectType = {}
|
||||||
|
|
||||||
get context () {
|
get context () {
|
||||||
return this.defineModel({
|
return this.defineModel({
|
||||||
@ -322,6 +323,7 @@ export default class FormularioInput extends Vue {
|
|||||||
this.performValidation()
|
this.performValidation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// noinspection JSUnusedGlobalSymbols
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
if (!this.disableErrors && typeof this.removeErrorObserver === 'function') {
|
if (!this.disableErrors && typeof this.removeErrorObserver === 'function') {
|
||||||
this.removeErrorObserver(this.setErrors)
|
this.removeErrorObserver(this.setErrors)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Formulario } from '@/Formulario'
|
import { Formulario } from '@/Formulario'
|
||||||
import FormularioInput from '@/FormularioInput.vue'
|
import FormularioInput from '@/FormularioInput.vue'
|
||||||
import { ValidationContext } from '@/validation.types'
|
import { ValidationContext } from '@/validation/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an object of functions that each produce valid responses. There's no
|
* This is an object of functions that each produce valid responses. There's no
|
||||||
@ -216,6 +216,6 @@ const validationMessages = {
|
|||||||
* This creates a vue-formulario plugin that can be imported and used on each
|
* This creates a vue-formulario plugin that can be imported and used on each
|
||||||
* project.
|
* project.
|
||||||
*/
|
*/
|
||||||
export default function (instance: Formulario) {
|
export default function (instance: Formulario): void {
|
||||||
instance.extend({ validationMessages })
|
instance.extend({ validationMessages })
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@ import FormularioInput from '@/FormularioInput.vue'
|
|||||||
* important for features such as grouped fields.
|
* important for features such as grouped fields.
|
||||||
*/
|
*/
|
||||||
export default class Registry {
|
export default class Registry {
|
||||||
public ctx: FormularioForm
|
private ctx: FormularioForm
|
||||||
private registry: Map<string, FormularioForm>
|
private registry: Map<string, FormularioInput>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new registry of components.
|
* Create a new registry of components.
|
||||||
@ -23,7 +23,7 @@ export default class Registry {
|
|||||||
/**
|
/**
|
||||||
* Add an item to the registry.
|
* Add an item to the registry.
|
||||||
*/
|
*/
|
||||||
add (name: string, component: FormularioForm) {
|
add (name: string, component: FormularioInput) {
|
||||||
this.registry.set(name, component)
|
this.registry.set(name, component)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ export default class Registry {
|
|||||||
/**
|
/**
|
||||||
* Get a particular registry value.
|
* Get a particular registry value.
|
||||||
*/
|
*/
|
||||||
get (key: string): FormularioForm | undefined {
|
get (key: string): FormularioInput | undefined {
|
||||||
return this.registry.get(key)
|
return this.registry.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,18 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import isUrl from 'is-url'
|
import isUrl from 'is-url'
|
||||||
import FileUpload from '../FileUpload'
|
import FileUpload from '../FileUpload'
|
||||||
import { shallowEqualObjects, regexForFormat, has } from './utils'
|
import { shallowEqualObjects, regexForFormat, has } from '@/libs/utils'
|
||||||
import { ObjectType } from '@/common.types'
|
import { ObjectType } from '@/common.types'
|
||||||
|
|
||||||
|
interface ValidatableData {
|
||||||
|
value: any,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConfirmValidatableData extends ValidatableData {
|
||||||
|
getFormValues: () => ObjectType,
|
||||||
|
name: string,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Library of rules
|
* Library of rules
|
||||||
*/
|
*/
|
||||||
@ -11,23 +20,23 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Rule: the value must be "yes", "on", "1", or true
|
* Rule: the value must be "yes", "on", "1", or true
|
||||||
*/
|
*/
|
||||||
accepted ({ value }: { value: any }) {
|
accepted ({ value }: ValidatableData): Promise<boolean> {
|
||||||
return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value))
|
return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: checks if a value is after a given date. Defaults to current time
|
* Rule: checks if a value is after a given date. Defaults to current time
|
||||||
*/
|
*/
|
||||||
after ({ value }: { value: string }, compare: string | false = false) {
|
after ({ value }: { value: Date|string }, compare: string | false = false): Promise<boolean> {
|
||||||
const timestamp = compare !== false ? Date.parse(compare) : new Date()
|
const timestamp = compare !== false ? Date.parse(compare) : Date.now()
|
||||||
const fieldValue = Date.parse(value)
|
const fieldValue = value instanceof Date ? value.getTime() : Date.parse(value)
|
||||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: checks if the value is only alpha
|
* Rule: checks if the value is only alpha
|
||||||
*/
|
*/
|
||||||
alpha ({ value }: { value: string }, set: string = 'default') {
|
alpha ({ value }: { value: string }, set: string = 'default'): Promise<boolean> {
|
||||||
const sets = {
|
const sets = {
|
||||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||||
latin: /^[a-zA-Z]+$/
|
latin: /^[a-zA-Z]+$/
|
||||||
@ -40,7 +49,7 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Rule: checks if the value is alpha numeric
|
* Rule: checks if the value is alpha numeric
|
||||||
*/
|
*/
|
||||||
alphanumeric ({ value }: { value: string }, set = 'default') {
|
alphanumeric ({ value }: { value: string }, set = 'default'): Promise<boolean> {
|
||||||
const sets = {
|
const sets = {
|
||||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||||
latin: /^[a-zA-Z0-9]+$/
|
latin: /^[a-zA-Z0-9]+$/
|
||||||
@ -53,16 +62,16 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Rule: checks if a value is after a given date. Defaults to current time
|
* Rule: checks if a value is after a given date. Defaults to current time
|
||||||
*/
|
*/
|
||||||
before ({ value }: { value: string }, compare: string | false = false) {
|
before ({ value }: { value: Date|string }, compare: string|false = false): Promise<boolean> {
|
||||||
const timestamp = compare !== false ? Date.parse(compare) : new Date()
|
const timestamp = compare !== false ? Date.parse(compare) : Date.now()
|
||||||
const fieldValue = Date.parse(value)
|
const fieldValue = value instanceof Date ? value.getTime() : Date.parse(value)
|
||||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: checks if the value is between two other values
|
* Rule: checks if the value is between two other values
|
||||||
*/
|
*/
|
||||||
between ({ value }: { value: string | number }, from: number = 0, to: number = 10, force: string) {
|
between ({ value }: { value: string|number }, from: number|any = 0, to: number|any = 10, force?: string): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
return Promise.resolve((() => {
|
||||||
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
||||||
return false
|
return false
|
||||||
@ -85,7 +94,7 @@ export default {
|
|||||||
* Confirm that the value of one field is the same as another, mostly used
|
* Confirm that the value of one field is the same as another, mostly used
|
||||||
* for password confirmations.
|
* for password confirmations.
|
||||||
*/
|
*/
|
||||||
confirm ({ value, getFormValues, name }: { value: any, getFormValues: () => ObjectType, name: string }, field: string) {
|
confirm ({ value, getFormValues, name }: ConfirmValidatableData, field?: string): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
return Promise.resolve((() => {
|
||||||
const formValues = getFormValues()
|
const formValues = getFormValues()
|
||||||
let confirmationFieldName = field
|
let confirmationFieldName = field
|
||||||
@ -100,64 +109,51 @@ export default {
|
|||||||
* Rule: ensures the value is a date according to Date.parse(), or a format
|
* Rule: ensures the value is a date according to Date.parse(), or a format
|
||||||
* regex.
|
* regex.
|
||||||
*/
|
*/
|
||||||
date ({ value }: { value: string }, format: string | false = false) {
|
date ({ value }: { value: string }, format: string | false = false): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
return Promise.resolve(format ? regexForFormat(format).test(value) : !isNaN(Date.parse(value)))
|
||||||
if (format) {
|
|
||||||
return regexForFormat(format).test(value)
|
|
||||||
}
|
|
||||||
return !isNaN(Date.parse(value))
|
|
||||||
})())
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: tests
|
* Rule: tests
|
||||||
*/
|
*/
|
||||||
email ({ value }: { value: string}) {
|
email ({ value }: { value: string }): Promise<boolean> {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Promise.resolve(() => { return true })
|
return Promise.resolve(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const isEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
|
const isEmail = /^(([^<>()\[\].,;:\s@"]+(\.[^<>()\[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i
|
||||||
return Promise.resolve(isEmail.test(value))
|
return Promise.resolve(isEmail.test(value))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: Value ends with one of the given Strings
|
* Rule: Value ends with one of the given Strings
|
||||||
*/
|
*/
|
||||||
endsWith: function ({ value }: any, ...stack: any[]) {
|
endsWith ({ value }: { value: any }, ...stack: any[]): Promise<boolean> {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Promise.resolve(() => { return true })
|
return Promise.resolve(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve((() => {
|
if (typeof value === 'string') {
|
||||||
if (typeof value === 'string' && stack.length) {
|
return Promise.resolve(stack.length === 0 || stack.some(str => value.endsWith(str)))
|
||||||
return stack.find(item => {
|
}
|
||||||
return value.endsWith(item)
|
|
||||||
}) !== undefined
|
return Promise.resolve(false)
|
||||||
} else if (typeof value === 'string' && stack.length === 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})())
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: Value is in an array (stack).
|
* Rule: Value is in an array (stack).
|
||||||
*/
|
*/
|
||||||
in: function ({ value }: any, ...stack: any[]) {
|
in ({ value }: { value: any }, ...stack: any[]): Promise<boolean> {
|
||||||
return Promise.resolve(stack.find(item => {
|
return Promise.resolve(stack.some(item => {
|
||||||
if (typeof item === 'object') {
|
return typeof item === 'object' ? shallowEqualObjects(item, value) : item === value
|
||||||
return shallowEqualObjects(item, value)
|
}))
|
||||||
}
|
|
||||||
return item === value
|
|
||||||
}) !== undefined)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: Match the value against a (stack) of patterns or strings
|
* Rule: Match the value against a (stack) of patterns or strings
|
||||||
*/
|
*/
|
||||||
matches: function ({ value }: any, ...stack: any[]) {
|
matches ({ value }: { value: any }, ...stack: any[]): Promise<boolean> {
|
||||||
return Promise.resolve(!!stack.find(pattern => {
|
return Promise.resolve(!!stack.find(pattern => {
|
||||||
if (typeof pattern === 'string' && pattern.substr(0, 1) === '/' && pattern.substr(-1) === '/') {
|
if (typeof pattern === 'string' && pattern.substr(0, 1) === '/' && pattern.substr(-1) === '/') {
|
||||||
pattern = new RegExp(pattern.substr(1, pattern.length - 2))
|
pattern = new RegExp(pattern.substr(1, pattern.length - 2))
|
||||||
@ -172,25 +168,22 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Check the file type is correct.
|
* Check the file type is correct.
|
||||||
*/
|
*/
|
||||||
mime: function ({ value }: any, ...types: string[]) {
|
mime ({ value }: { value: any }, ...types: string[]): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
if (value instanceof FileUpload) {
|
||||||
if (value instanceof FileUpload) {
|
const files = value.getFiles()
|
||||||
const fileList = value.getFiles()
|
const isMimeCorrect = (file: File) => types.includes(file.type)
|
||||||
for (let i = 0; i < fileList.length; i++) {
|
const allValid: boolean = files.reduce((valid: boolean, { file }) => valid && isMimeCorrect(file), true)
|
||||||
const file = fileList[i].file
|
|
||||||
if (!types.includes(file.type)) {
|
return Promise.resolve(allValid)
|
||||||
return false
|
}
|
||||||
}
|
|
||||||
}
|
return Promise.resolve(true)
|
||||||
}
|
|
||||||
return true
|
|
||||||
})())
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the minimum value of a particular.
|
* Check the minimum value of a particular.
|
||||||
*/
|
*/
|
||||||
min: function ({ value }: any, minimum = 1, force: string) {
|
min ({ value }: { value: any }, minimum: number | any = 1, force?: string): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
return Promise.resolve((() => {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
minimum = !isNaN(minimum) ? Number(minimum) : minimum
|
minimum = !isNaN(minimum) ? Number(minimum) : minimum
|
||||||
@ -211,10 +204,10 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Check the maximum value of a particular.
|
* Check the maximum value of a particular.
|
||||||
*/
|
*/
|
||||||
max: function ({ value }: any, maximum = 10, force: string) {
|
max ({ value }: { value: any }, maximum: string | number = 10, force?: string): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
return Promise.resolve((() => {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
maximum = !isNaN(maximum) ? Number(maximum) : maximum
|
maximum = !isNaN(Number(maximum)) ? Number(maximum) : maximum
|
||||||
return value.length <= maximum
|
return value.length <= maximum
|
||||||
}
|
}
|
||||||
if ((!isNaN(value) && force !== 'length') || force === 'value') {
|
if ((!isNaN(value) && force !== 'length') || force === 'value') {
|
||||||
@ -232,26 +225,23 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Rule: Value is not in stack.
|
* Rule: Value is not in stack.
|
||||||
*/
|
*/
|
||||||
not: function ({ value }: any, ...stack: any[]) {
|
not ({ value }: { value: any }, ...stack: any[]): Promise<boolean> {
|
||||||
return Promise.resolve(stack.find(item => {
|
return Promise.resolve(!stack.some(item => {
|
||||||
if (typeof item === 'object') {
|
return typeof item === 'object' ? shallowEqualObjects(item, value) : item === value
|
||||||
return shallowEqualObjects(item, value)
|
}))
|
||||||
}
|
|
||||||
return item === value
|
|
||||||
}) === undefined)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: checks if the value is only alpha numeric
|
* Rule: checks if the value is only alpha numeric
|
||||||
*/
|
*/
|
||||||
number ({ value }: { value: any }) {
|
number ({ value }: { value: any }): Promise<boolean> {
|
||||||
return Promise.resolve(!isNaN(value))
|
return Promise.resolve(!isNaN(Number(value)))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: must be a value
|
* Rule: must be a value
|
||||||
*/
|
*/
|
||||||
required ({ value }: any, isRequired: string|boolean = true) {
|
required ({ value }: { value: any }, isRequired: string|boolean = true): Promise<boolean> {
|
||||||
return Promise.resolve((() => {
|
return Promise.resolve((() => {
|
||||||
if (!isRequired || ['no', 'false'].includes(isRequired as string)) {
|
if (!isRequired || ['no', 'false'].includes(isRequired as string)) {
|
||||||
return true
|
return true
|
||||||
@ -275,32 +265,29 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Rule: Value starts with one of the given Strings
|
* Rule: Value starts with one of the given Strings
|
||||||
*/
|
*/
|
||||||
startsWith ({ value }: { value: any }, ...stack: any[]) {
|
startsWith ({ value }: { value: any }, ...stack: string[]): Promise<boolean> {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Promise.resolve(() => { return true })
|
return Promise.resolve(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve((() => {
|
if (typeof value === 'string') {
|
||||||
if (typeof value === 'string' && stack.length) {
|
return Promise.resolve(stack.length === 0 || stack.some(str => value.startsWith(str)))
|
||||||
return stack.find(item => value.startsWith(item)) !== undefined
|
}
|
||||||
} else if (typeof value === 'string' && stack.length === 0) {
|
|
||||||
return true
|
return Promise.resolve(false)
|
||||||
}
|
|
||||||
return false
|
|
||||||
})())
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: checks if a string is a valid url
|
* Rule: checks if a string is a valid url
|
||||||
*/
|
*/
|
||||||
url ({ value }: { value: string }) {
|
url ({ value }: { value: string }): Promise<boolean> {
|
||||||
return Promise.resolve(isUrl(value))
|
return Promise.resolve(isUrl(value))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rule: not a true rule — more like a compiler flag.
|
* Rule: not a true rule — more like a compiler flag.
|
||||||
*/
|
*/
|
||||||
bail () {
|
bail (): Promise<boolean> {
|
||||||
return Promise.resolve(true)
|
return Promise.resolve(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,8 +14,8 @@ describe('FormularioGrouping', () => {
|
|||||||
slots: {
|
slots: {
|
||||||
default: `
|
default: `
|
||||||
<FormularioGrouping name="sub">
|
<FormularioGrouping name="sub">
|
||||||
<FormularioInput name="text" v-slot="vSlot">
|
<FormularioInput name="text" v-slot="{ context }">
|
||||||
<input type="text" v-model="vSlot.context.model">
|
<input type="text" v-model="context.model">
|
||||||
</FormularioInput>
|
</FormularioInput>
|
||||||
</FormularioGrouping>
|
</FormularioGrouping>
|
||||||
`
|
`
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import rules from '@/libs/rules'
|
import rules from '@/validation/rules.ts'
|
||||||
import FileUpload from '../../src/FileUpload'
|
import FileUpload from '../../src/FileUpload'
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { parseRules, parseLocale, regexForFormat, cloneDeep, isScalar, snakeToCamel, groupBails } from '@/libs/utils'
|
import { parseRules, parseLocale, regexForFormat, cloneDeep, isScalar, snakeToCamel, groupBails } from '@/libs/utils'
|
||||||
import rules from '@/libs/rules'
|
import rules from '@/validation/rules.ts'
|
||||||
import FileUpload from '@/FileUpload';
|
import FileUpload from '@/FileUpload'
|
||||||
|
|
||||||
describe('parseRules', () => {
|
describe('parseRules', () => {
|
||||||
it('parses single string rules, returning empty arguments array', () => {
|
it('parses single string rules, returning empty arguments array', () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user