Skip to content

Commit

Permalink
Merge 75c1e57 into def5a89
Browse files Browse the repository at this point in the history
  • Loading branch information
mushan0x0 committed Nov 1, 2018
2 parents def5a89 + 75c1e57 commit 27045ea
Show file tree
Hide file tree
Showing 14 changed files with 316 additions and 77 deletions.
4 changes: 4 additions & 0 deletions .babelrc
@@ -0,0 +1,4 @@
{
"presets": ["env"],
"plugins": ["transform-runtime"]
}
102 changes: 80 additions & 22 deletions README.md
Expand Up @@ -35,8 +35,12 @@ Basic usage involves defining a descriptor, assigning it to a schema and passing
```javascript
var schema = require('async-validator');
var descriptor = {
name: {type: "string", required: true}
}
name: {
type: "string",
required: true,
validator: (rule, value) => value === 'muji',
},
};
var validator = new schema(descriptor);
validator.validate({name: "muji"}, (errors, fields) => {
if(errors) {
Expand All @@ -47,18 +51,42 @@ validator.validate({name: "muji"}, (errors, fields) => {
}
// validation passed
});

// PROMISE USAGE
validator.validate({
name: "muji",
asyncValidator: (rule, value) => axios.post('/nameValidator', { name: value }),
}, (errors, fields) => {
if(errors) {
// validation failed, errors is an array of all errors
// fields is an object keyed by field name with an array of
// errors per field
return handleErrors(errors, fields);
}
// validation passed
})
.then(() => {
// validation passed
})
.catch(({ errors, fields }) => {
return handleErrors(errors, fields);
})
```

### Validate

```javascript
function(source, [options], callback)
function(source, [options], callback): Promise
```

* `source`: The object to validate (required).
* `options`: An object describing processing options for the validation (optional).
* `callback`: A callback function to invoke when validation completes (required).

The method will return a Promise object like:
* `then()`,validation passed
* `catch({ errors, fields })`,validation failed, errors is an array of all errors, fields is an object keyed by field name with an array of
### Options
* `first`: Boolean, Invoke `callback` when the first validation rule generates an error,
Expand All @@ -78,12 +106,12 @@ function(rule, value, callback, source, options)

* `rule`: The validation rule in the source descriptor that corresponds to the field name being validated. It is always assigned a `field` property with the name of the field being validated.
* `value`: The value of the source object property being validated.
* `callback`: A callback function to invoke once validation is complete. It expects to be passed an array of `Error` instances to indicate validation failure.
* `callback`: A callback function to invoke once validation is complete. It expects to be passed an array of `Error` instances to indicate validation failure. If the check is synchronous, you can directly return a ` false ` or ` Error ` or ` Error Array `.
* `source`: The source object that was passed to the `validate` method.
* `options`: Additional options.
* `options.messages`: The object containing validation error messages, will be deep merged with defaultMessages.

The options passed to `validate` are passed on to the validation functions so that you may reference transient data (such as model references) in validation functions. However, some option names are reserved; if you use these properties of the options object they are overwritten. The reserved properties are `messages`, `exception` and `error`.
The options passed to `validate` or `asyncValidate` are passed on to the validation functions so that you may reference transient data (such as model references) in validation functions. However, some option names are reserved; if you use these properties of the options object they are overwritten. The reserved properties are `messages`, `exception` and `error`.

```javascript
var schema = require('async-validator');
Expand All @@ -96,7 +124,7 @@ var descriptor = {
util.format("%s must be lowercase alphanumeric characters",
rule.field)));
}
callback(errors);
return errors;
}
}
var validator = new schema(descriptor);
Expand All @@ -118,7 +146,7 @@ var descriptor = {
var errors = [];
// test if email address already exists in a database
// and add a validation error to the errors array if it does
callback(errors);
return errors;
}}
]
}
Expand Down Expand Up @@ -217,9 +245,10 @@ var descriptor = {
name: {type: "string", required: true}
}
var validator = new schema(descriptor);
validator.validate({ address: {} }, (errors, fields) => {
// now only errors for street and name
});
validator.validate({ address: {} })
.catch(({ errors, fields }) => {
// now only errors for street and name
});
```

The parent rule is also validated so if you have a set of rules such as:
Expand Down Expand Up @@ -273,9 +302,8 @@ var descriptor = {
}
var validator = new schema(descriptor);
var source = {name: " user "};
validator.validate(source, (errors, fields) => {
assert.equal(source.name, "user");
});
validator.validate(source)
.then(() => assert.equal(source.name, "user"));
```

Without the `transform` function validation would fail due to the pattern not matching as the input contains leading and trailing whitespace, but by adding the transform function validation passes and the field value is sanitized at the same time.
Expand Down Expand Up @@ -315,14 +343,14 @@ validator.messages(cn);

If you are defining your own validation functions it is better practice to assign the message strings to a messages object and then access the messages via the `options.messages` property within the validation function.

### validator
### asyncValidator

you can custom validate function for specified field:
You can customize the asynchronous validation function for the specified field:

```js
const fields = {
asyncField:{
validator(rule,value,callback){
asyncValidator(rule,value,callback){
ajax({
url:'xx',
value:value
Expand All @@ -335,13 +363,43 @@ const fields = {
},

promiseField:{
validator(rule, value){
return ajax({
url:'xx',
value:value
});
}
asyncValidator(rule, value){
return ajax({
url:'xx',
value:value
});
}
}
};
```

### validator

you can custom validate function for specified field:

```js
const fields = {
field:{
validator(rule,value,callback){
return value === 'test';
},
message: 'Value is not equal to "test".',
},

field2:{
validator(rule,value,callback){
return new Error(`'${value} is not equal to "test".'`);
},
},

arrField:{
validator(rule, value){
return [
new Error('Message 1'),
new Error('Message 2'),
];
}
},
};
```

Expand Down
69 changes: 51 additions & 18 deletions __tests__/promise.spec.js
@@ -1,19 +1,19 @@
import Schema from '../src/';

describe('validator', () => {
describe('asyncValidator', () => {
it('works', (done) => {
new Schema({
v: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e1'));
},
}, {
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e2'));
},
}],
v2: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e3'));
},
}],
Expand All @@ -31,16 +31,16 @@ describe('validator', () => {
it('first works', (done) => {
new Schema({
v: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e1'));
},
}, {
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e2'));
},
}],
v2: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e3'));
},
}],
Expand All @@ -60,26 +60,26 @@ describe('validator', () => {
it('works for true', (done) => {
new Schema({
v: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e1'));
},
}, {
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e2'));
},
}],

v2: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e3'));
},
}],
v3: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e4'));
},
}, {
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e5'));
},
}],
Expand All @@ -101,43 +101,76 @@ describe('validator', () => {
it('works for array', (done) => {
new Schema({
v: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e1'));
},
}, {
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e2'));
},
}],

v2: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e3'));
},
}],
v3: [{
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e4'));
},
}, {
validator(rule, value) {
asyncValidator(rule, value) {
return Promise.reject(new Error('e5'));
},
}],
v4: [{
asyncValidator: () => new Promise((resolve, reject) => {
setTimeout(resolve, 100)
}),
}, {
asyncValidator: () => new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('e6')), 100)
}),
}]
}).validate({
v: 1,
v2: 1,
v3: 1,
}, {
firstFields: ['v'],
}, (errors) => {
expect(errors.length).toBe(4);
expect(errors.length).toBe(5);
expect(errors[0].message).toBe('e1');
expect(errors[1].message).toBe('e3');
expect(errors[2].message).toBe('e4');
expect(errors[3].message).toBe('e5');
expect(errors[4].message).toBe('e6');
done();
});
});
it('Whether to remove the \'Uncaught (in promise)\' warning', async (done) => {
let allCorrect = true;
try {
await new Schema({
async: {
asyncValidator(rule, value) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject([new Error(rule.message)]);
}, 100);
})
},
message: 'async fails',
},
}).validate({
v: 1,
});
} catch ({ errors }) {
allCorrect = errors.length === 1;
}
expect(allCorrect).toBe(true);
done()
});
});
});
23 changes: 22 additions & 1 deletion __tests__/validator.spec.js
Expand Up @@ -18,13 +18,34 @@ describe('validator', () => {
callback(new Error('e3'));
},
}],
v3: [{
validator() {
return false;
},
}, {
validator() {
return new Error('e5');
},
}, {
validator() {
return false;
},
message: 'e6',
}, {
validator() {
return true;
},
}],
}).validate({
v: 2,
}, (errors) => {
expect(errors.length).toBe(3);
expect(errors.length).toBe(6);
expect(errors[0].message).toBe('e1');
expect(errors[1].message).toBe('e2');
expect(errors[2].message).toBe('e3');
expect(errors[3].message).toBe('v3 fails');
expect(errors[4].message).toBe('e5');
expect(errors[5].message).toBe('e6');
done();
});
});
Expand Down
Empty file added examples/async-validator.html
Empty file.

0 comments on commit 27045ea

Please sign in to comment.