diff --git a/package.json b/package.json
index 19038c3..82c7778 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@wgr-sa/nuxt-form",
"description": "Form builder for Nuxt",
- "version": "0.8.9",
+ "version": "0.9.0",
"repository": "https://github.com/WGR-SA/nuxt-form.git",
"author": "jeanvier",
"license": "MIT",
diff --git a/playground/app.vue b/playground/app.vue
index 820a5f3..b3cecad 100644
--- a/playground/app.vue
+++ b/playground/app.vue
@@ -3,6 +3,9 @@
// watchEffect(() => {
// if testForm.value.isReady()
// testForm.value.submit()
+
+import { max } from 'class-validator';
+
// })
@@ -12,15 +15,15 @@
ref="testForm"
action="https://httpbin.org/post"
>
-
-
-
-
-
-
+ /> -->
+
+
+
+
Submit
diff --git a/src/runtime/composables/validator.ts b/src/runtime/composables/validator.ts
index a1ceac6..4c08884 100644
--- a/src/runtime/composables/validator.ts
+++ b/src/runtime/composables/validator.ts
@@ -3,43 +3,71 @@ import * as validators from 'class-validator'
import { Form } from '#imports'
export const useFormValidator = () => {
+ const validatorTypeMap = new Map([
+ ['number', ['isNumber', 'min', 'max', 'isInt', 'isFloat', 'isDivisibleBy', 'isPositive', 'isNegative', 'isLessThan', 'isGreaterThan', 'isLatitude', 'isLongitude', 'isPort']],
+ ['date', ['isDate', 'minDate', 'maxDate', 'isBefore', 'isAfter']],
+ ['boolean', ['isBoolean']],
+ ['array', ['arrayContains', 'arrayNotContains', 'arrayNotEmpty', 'arrayUnique']]
+ ])
- const getFieldErrors = (form: Form, field: string): string[] => {
-
- const errors = ref([])
+ const getExpectedType = (validatorName: string): string => {
+ for (const [type, validatorList] of validatorTypeMap) {
+ if (validatorList.includes(validatorName)) return type
+ }
+ return 'string'
+ }
- if (!form.validator.rules[field]) {
- return []
- }
+ const convertValue = (value: string, expectedType: string): any => {
+ switch (expectedType) {
+ case 'number': return Number(value)
+ case 'boolean': return value.toLowerCase() === 'true'
+ case 'date': return new Date(value)
+ case 'array': return tryParseJSON(value) ?? value.split(',').map(item => item.trim())
+ default: return value
+ }
+ }
- form.validator.rules[field].forEach((rule: any) => {
-
- const validator = validators[rule.$params.type as keyof typeof validators]
+ const tryParseJSON = (value: string): any => {
+ try {
+ return JSON.parse(value)
+ } catch {
+ return 2
+ }
+ }
+ const getFieldErrors = (form: Form, field: string): string[] => {
+ if (!form.validator.rules[field]) return []
- const type_rules = [ 'isEmail', 'isNumber' ]
- // validate type only if field is not empty
- if (type_rules.includes(rule.$params.type) && (form.data.state[field].length === 0 || form.data.state[field] === null)) {
- return
+ const errors: string[] = []
+ const fieldValue = form.data.state[field]
+
+ for (const rule of form.validator.rules[field]) {
+ const validatorName = rule.$params.type as keyof typeof validators
+ const validator = validators[validatorName]
+
+ if (!validator) {
+ console.error(`Validator ${validatorName} not found`)
+ continue
}
- if (field in form.data.state) {
- // @ts-ignore TODO: import only validation functions
- const result = validator(form.data.state[field].toString(), rule.$params.options)
+ if (['isEmail', 'isNumber'].includes(validatorName) && !fieldValue) continue
- if (!result && (form.data.state[field].length > 0 && form.data.state[field] !== 'false' || ['error', 'validate'].includes(form.state.status))) {
- errors.value.push(rule.custom_message ?? rule.$message)
+ if (fieldValue !== undefined) {
+ const expectedType = getExpectedType(validatorName)
+ const convertedValue = convertValue(fieldValue, expectedType)
+
+ if (!validator(convertedValue, ...(rule.$params.options || [])) &&
+ (fieldValue.length > 0 && fieldValue !== 'false' || ['error', 'validate'].includes(form.state.status))) {
+ errors.push(rule.custom_message ?? rule.$message)
}
}
-
- })
+ }
- return errors.value
+ return errors
}
- const validateFields = async (form: Form): Promise => {
- return !Object.keys(form.validator.rules).some((field: string) => getFieldErrors(form, field).length > 0)
- }
+ const validateFields = (form: Form): boolean =>
+ Object.keys(form.validator.rules).every((field: string) => getFieldErrors(form, field).length === 0)
return {
getFieldErrors,
diff --git a/src/runtime/messages/validators/en.ts b/src/runtime/messages/validators/en.ts
index 288b2bb..69ca470 100644
--- a/src/runtime/messages/validators/en.ts
+++ b/src/runtime/messages/validators/en.ts
@@ -2,6 +2,8 @@ export const en: {[key: string]: string} = {
equals: 'This field must be equal to {0}',
contains: 'This field must contain {0}',
matches: 'This field must match the format {0}',
+ max: 'This field must be less than or equal to {0}',
+ min: 'This field must be greater than or equal to {0}',
isEmail: 'This field must be a valid email address',
isURL: 'This field must be a valid URL',
isMACAddress: 'This field must be a valid MAC address',
diff --git a/src/runtime/messages/validators/fr.ts b/src/runtime/messages/validators/fr.ts
index 5484459..8c37c60 100644
--- a/src/runtime/messages/validators/fr.ts
+++ b/src/runtime/messages/validators/fr.ts
@@ -2,6 +2,8 @@ export const fr: {[key: string]: string} = {
equals: 'Ce champ doit être égal à {0}',
contains: 'Ce champ doit contenir {0}',
matches: 'Ce champ doit correspondre au format {0}',
+ min: 'Ce champ doit être supérieur ou égal à {0}',
+ max: 'Ce champ doit être inférieur ou égal à {0}',
isEmail: 'Ce champ doit être une adresse email valide',
isURL: 'Ce champ doit être une URL valide',
isMACAddress: 'Ce champ doit être une adresse MAC valide',
diff --git a/src/runtime/utils/validators/validator.ts b/src/runtime/utils/validators/validator.ts
index 620a855..c322f4a 100644
--- a/src/runtime/utils/validators/validator.ts
+++ b/src/runtime/utils/validators/validator.ts
@@ -9,7 +9,7 @@ export class FormValidator {
return { $params: { type: r }, $message: r }
}
const rule = Object.keys(r)[0]
- return { $params: { type: rule, options: [...r[rule]] }, $message: r, custom_message: r.message }
+ return { $params: { type: rule, options: [...r[rule]] }, $message: rule, custom_message: r.message }
})
this.updateValidatorMessages(options.messages)