diff --git a/README.md b/README.md index 945942d..c92e7b5 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,7 @@ type ValidatorResult = null | Errors; | pattern | `pattern: RegExp` | | email | - | | equalToControl | `controlName: string` | +| callback | `(value: any, control: Control) => boolean` | Options are passed via props ```jsx diff --git a/__tests__/form.test.tsx b/__tests__/form.test.tsx index 86c901e..fe198cf 100644 --- a/__tests__/form.test.tsx +++ b/__tests__/form.test.tsx @@ -624,3 +624,38 @@ test('onChange callback', () => { bar: 'qux' }); }); + +test('callback validator', () => { + const wrapper = mount( +
+ { _ => ( + + value !== 'qux'}> + { control => ( + control.onChange(event.target.value)} + /> + ) } + + + ) } +
+ ); + + const instance = wrapper.instance() as Form; + + instance.setValue('foo', 'foobar'); + + expect(instance.errors) + .toEqual({ + foo: {}, + }); + + instance.setValue('foo', 'qux'); + + expect(instance.errors) + .toEqual({ + foo: { callback: true }, + }); +}); diff --git a/__tests__/validators.test.ts b/__tests__/validators.test.ts index b6747b8..390c823 100644 --- a/__tests__/validators.test.ts +++ b/__tests__/validators.test.ts @@ -76,3 +76,19 @@ test('equalToControl', () => { expect(Validators.get('equalToControl')('bar', 'foo', mockControl as any)) .toBeNull(); }); + +test('callback', () => { + const mockControl = { + get form() { + return { + getValue() { return 'bar'; } + } + } + }; + + expect(Validators.get('callback')('bar', (value: any) => value !== 'bar', mockControl as any)) + .toEqual({ callback: true }); + + expect(Validators.get('callback')('baz', (value: any) => value !== 'bar', mockControl as any)) + .toBeNull(); +}); diff --git a/src/control.ts b/src/control.ts index e12ca03..7ee2b2c 100644 --- a/src/control.ts +++ b/src/control.ts @@ -15,7 +15,7 @@ function isValidationRulesChanged( } for (const rule of oldRules) { - if (currentProps[rule] !== nextProps[rule]) { + if ('function' !== typeof currentProps[rule] && currentProps[rule] !== nextProps[rule]) { return true; } } diff --git a/src/validators.ts b/src/validators.ts index ec95925..291d860 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -58,6 +58,14 @@ validators.set('equalToControl', (val: any, controlName: string, control: Contro return val === control.form.getValue(controlName) ? null : { equalToControl: true }; }); +validators.set('callback', (val: any, fn: (value: any, control: Control) => boolean, control: Control) => { + if (isEmpty(val)) { + return null; + } + + return fn(val, control) ? null : { callback: true }; +}); + export default { delete(v: string) { return validators.delete(v); }, add(v: string, fn: Validator) { return validators.set(v, fn); },