1
0
mirror of synced 2024-11-25 14:56:03 +03:00

Validation labels are no longer part of the validation rule string, but retrieved from props on formualte-element

This commit is contained in:
Justin Schroeder 2018-02-01 10:47:11 -05:00
parent 7a54322e57
commit ab1330f27f
7 changed files with 43 additions and 33 deletions

View File

@ -130,19 +130,20 @@ simply chain your rules with pipes `|'. Additional arguments can be passed to
validation rules by using parenthesis after the rule name:
```
validation="required(My Label)|confirmed(Password Field, confirmation_field)"
validation="required|confirmed(confirmation_field)"
```
By convention the first argument is an alternate label for use in error messages.
This is still a fresh project, so pull requests for more built-in rules are
appreciated!
The field label used in built in validation methods is the `validationLabel`
attribute on your `formulate-element`. If no `validationLabel` is found then
the `label` attribute is used, and if no `label` attribute is found it will
fall back to the fields `name` attribute (which is required).
#### Custom Validation Rules
Validation rules are easy to write! They're just simple functions that are
always passed at least one argument, an object containing the `field` name,
`value` of the field, `error` function to generate an error message, and all the
`values` of the entire form.
`value` of the field, validation `label`, `error` function to generate an error
message, and an object containing all the `values` for the entire form.
Additionally, validation rules can pass an unlimited number of extra arguments.
These arguments are passed as the 2nd-nth arguments to the validation rule.
@ -151,10 +152,10 @@ attribute on the `formulate-element`.
```html
<formulate-element
type="checkbox"
name="terms"
label="Please agree to our terms of service"
validation="required(Terms of service)"
type="password"
name="password"
label="Password"
validation="confirmed(password_confirmation_field)"
/>
```
@ -167,8 +168,8 @@ of rule functions in the plugins installation call:
```js
Vue.use(formulate, {
rules: {
isPizza ({field, value, error, values}, label) {
return value === 'pizza' ? false : `That is not pizza.`
isPizza ({field, value, error, values, label}) {
return value === 'pizza' ? false : `label is not pizza.`
}
}
})

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -100,10 +100,11 @@ export default {
form: this.name
}))
},
async validateField ({field, validation}) {
async validateField ({field, validation, label}) {
let errors = await this.$formulate.validationErrors({
field,
value: this.values[field]
value: this.values[field],
label
}, validation, this.values)
if (!equals(errors || [], (this.validationErrors[field] || []))) {
this.updateFieldValidationErrors({field, errors: errors || []})
@ -111,9 +112,13 @@ export default {
return errors
},
updateFormValidation () {
this.fields.map(field => {
console.log(field.validationLabel || field.label || field.name)
})
this.fields.map(async field => this.validateField({
field: field.name,
validation: field.validation
validation: field.validation,
label: field.validationLabel || field.label || field.name
}))
},
submit () {

View File

@ -1,6 +1,6 @@
export default {
required: ({field, value}, label) => `${label || field} is required`,
email: ({field, value}, label) => `${label || 'Email address'} is invalid.`,
confirmed: ({field, value}, label) => `${label || field} does not match the confirmation field.`,
default: ({field, value}) => `The ${field} field is invalid.`
required: ({label, value}) => `${label} is required`,
email: ({label, value}) => `${label} is invalid.`,
confirmed: ({label, value}) => `${label} does not match the confirmation field.`,
default: ({label, value}) => `This field is invalid.`
}

View File

@ -93,10 +93,10 @@ class Formulate {
* @param {string} rulesString
* @param {Object} values
*/
async validationErrors ({field, value}, rulesString, values) {
async validationErrors ({field, value, label}, rulesString, values) {
return rulesString ? Promise.all(
this.parseRules(rulesString)
.map(({rule, args}) => this.rules[rule]({field, value, error: this.errorFactory(rule), values}, ...args))
.map(({rule, args}) => this.rules[rule]({field, value, label, error: this.errorFactory(rule), values}, ...args))
).then(responses => responses.reduce((errors, error) => {
return error ? (Array.isArray(errors) ? errors.concat(error) : [error]) : errors
}, false)) : false

View File

@ -4,7 +4,7 @@ export default {
* @param {Object} field
* @param {string} label
*/
async required ({field, value, error}, label) {
async required ({value, error}) {
return (!value || (Array.isArray(value) && !value.length)) ? error(...arguments) : false
},
@ -13,7 +13,7 @@ export default {
* @param {Object} field
* @param {string} label
*/
async email ({field, value, error}, label) {
async email ({value, error}) {
// eslint-disable-next-line
var re = /^(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/;
return (value && !re.test(value.toLowerCase())) ? error(...arguments) : false
@ -25,7 +25,7 @@ export default {
* @param {string} label
* @param {string} confirmField (uses `${field}_confirmation` by default)
*/
async confirmed ({field, value, error, values}, label, confirmField) {
async confirmed ({field, value, error, values}, confirmField) {
confirmField = confirmField || `${field}_confirmation`
return (value && value !== values[confirmField]) ? error(...arguments) : false
}

View File

@ -2,18 +2,18 @@ import test from 'ava'
import f from '../dist'
const rules = f.rules
const error = ({field, value}, label) => {
const error = ({field, value, label}) => {
return `${field}${label}`
}
test('test required rule failure', async t => {
let v = await rules.required({field: 'name', value: '', error}, 'xyz')
let v = await rules.required({field: 'name', value: '', error, label: 'xyz'})
t.is('string', typeof v)
t.is('namexyz', v)
})
test('test required rule empty array failure', async t => {
let v = await rules.required({field: 'name', value: [], error}, 'xyz')
let v = await rules.required({field: 'name', value: [], error, label: 'xyz'})
t.is('namexyz', v)
})
@ -26,7 +26,7 @@ test('test email rule with valid email', async t => {
})
test('test email rule with invalid email', async t => {
t.is('email123', await rules.email({field: 'email', value: 'invalid@example', error}, '123'))
t.is('email123', await rules.email({field: 'email', value: 'invalid@example', error, label: '123'}))
})
test('test email with empty email', async t => {
@ -37,34 +37,38 @@ test('test confirmed passes', async t => {
t.is(false, await rules.confirmed({
field: 'password',
value: 'password',
label: '123',
error,
values: {password_confirmation: 'password'}
}, '123'))
}))
})
test('test confirmed passes custom field', async t => {
t.is(false, await rules.confirmed({
field: 'password',
value: 'password',
label: '123',
error,
values: {customfield: 'password'}
}, '123', 'customfield'))
}, 'customfield'))
})
test('test confirmed fails', async t => {
t.is('password123', await rules.confirmed({
field: 'password',
value: 'password',
label: '123',
error,
values: {password_confirmation: 'pAssword'}
}, '123'))
}))
})
test('test empty confirmed passes', async t => {
t.is(false, await rules.confirmed({
field: 'password',
value: '',
label: '123',
error,
values: {password_confirmation: ''}
}, '123'))
}))
})