From 39a4e679513e3fa716b46cedce24931b3b57028f Mon Sep 17 00:00:00 2001 From: Romke van der Meulen Date: Fri, 18 Oct 2019 17:32:43 +0200 Subject: [PATCH 1/4] feat(config): support global config option for default validation trigger --- src/aurelia-validation.ts | 26 ++------------ src/config.ts | 36 +++++++++++++++++++ src/validation-controller-factory.ts | 4 ++- src/validation-controller.ts | 13 +++++-- test/validation-controller-factory.ts | 50 +++++++++++++++------------ 5 files changed, 79 insertions(+), 50 deletions(-) create mode 100644 src/config.ts diff --git a/src/aurelia-validation.ts b/src/aurelia-validation.ts index 24ac3568..18ff40ac 100644 --- a/src/aurelia-validation.ts +++ b/src/aurelia-validation.ts @@ -1,5 +1,6 @@ // Exports +export * from './config'; export * from './controller-validate-result'; export * from './get-target-dom-element'; export * from './property-info'; @@ -26,8 +27,7 @@ export * from './implementation/validation-rules'; // Configuration import { Container } from 'aurelia-dependency-injection'; -import { Validator } from './validator'; -import { StandardValidator } from './implementation/standard-validator'; +import { AureliaValidationConfiguration } from './config'; import { ValidationMessageParser } from './implementation/validation-message-parser'; import { PropertyAccessorParser } from './property-accessor-parser'; import { ValidationRules } from './implementation/validation-rules'; @@ -41,28 +41,6 @@ import { import { ValidationErrorsCustomAttribute } from './validation-errors-custom-attribute'; import { ValidationRendererCustomAttribute } from './validation-renderer-custom-attribute'; -/** - * Aurelia Validation Configuration API - */ -export class AureliaValidationConfiguration { - private validatorType: { new (...args: any[]): Validator } = StandardValidator; - - /** - * Use a custom Validator implementation. - */ - public customValidator(type: { new (...args: any[]): Validator }) { - this.validatorType = type; - } - - /** - * Applies the configuration. - */ - public apply(container: Container) { - const validator = container.get(this.validatorType); - container.registerInstance(Validator, validator); - } -} - /** * Configures the plugin. */ diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 00000000..cde94c3c --- /dev/null +++ b/src/config.ts @@ -0,0 +1,36 @@ +import { Container } from 'aurelia-dependency-injection'; +import { Validator } from './validator'; +import { StandardValidator } from './implementation/standard-validator'; +import { validateTrigger } from './validate-trigger'; + +/** + * Aurelia Validation Configuration API + */ +export class AureliaValidationConfiguration { + private validatorType: { new (...args: any[]): Validator } = StandardValidator; + private validationTrigger = validateTrigger.blur; + + /** + * Use a custom Validator implementation. + */ + public customValidator(type: { new (...args: any[]): Validator }) { + this.validatorType = type; + } + + public defaultValidationTrigger(trigger: validateTrigger) { + this.validationTrigger = trigger; + } + + public getDefaultValidationTrigger() { + return this.validationTrigger; + } + + /** + * Applies the configuration. + */ + public apply(container: Container) { + const validator = container.get(this.validatorType); + container.registerInstance(Validator, validator); + container.registerInstance(AureliaValidationConfiguration, this); + } +} diff --git a/src/validation-controller-factory.ts b/src/validation-controller-factory.ts index 15a25ba9..5d93b0f4 100644 --- a/src/validation-controller-factory.ts +++ b/src/validation-controller-factory.ts @@ -1,4 +1,5 @@ import { Container } from 'aurelia-dependency-injection'; +import { AureliaValidationConfiguration } from './config'; import { ValidationController } from './validation-controller'; import { Validator } from './validator'; import { PropertyAccessorParser } from './property-accessor-parser'; @@ -21,7 +22,8 @@ export class ValidationControllerFactory { validator = this.container.get(Validator) as Validator; } const propertyParser = this.container.get(PropertyAccessorParser) as PropertyAccessorParser; - return new ValidationController(validator, propertyParser); + const config = this.container.get(AureliaValidationConfiguration) as AureliaValidationConfiguration; + return new ValidationController(validator, propertyParser, config); } /** diff --git a/src/validation-controller.ts b/src/validation-controller.ts index 24683658..941ed8f0 100644 --- a/src/validation-controller.ts +++ b/src/validation-controller.ts @@ -1,4 +1,5 @@ import { Binding, Expression } from 'aurelia-binding'; +import { AureliaValidationConfiguration } from './config'; import { Validator } from './validator'; import { validateTrigger } from './validate-trigger'; import { getPropertyInfo } from './property-info'; @@ -15,7 +16,7 @@ import { ValidateEvent } from './validate-event'; * Exposes the current list of validation results for binding purposes. */ export class ValidationController { - public static inject = [Validator, PropertyAccessorParser]; + public static inject = [Validator, PropertyAccessorParser, AureliaValidationConfiguration]; // Registered bindings (via the validate binding behavior) private bindings = new Map(); @@ -47,14 +48,20 @@ export class ValidationController { /** * The trigger that will invoke automatic validation of a property used in a binding. */ - public validateTrigger = validateTrigger.blur; + public validateTrigger: validateTrigger; // Promise that resolves when validation has completed. private finishValidating: Promise = Promise.resolve(); private eventCallbacks: ((event: ValidateEvent) => void)[] = []; - constructor(private validator: Validator, private propertyParser: PropertyAccessorParser) { } + constructor( + private validator: Validator, + private propertyParser: PropertyAccessorParser, + config: AureliaValidationConfiguration, + ) { + this.validateTrigger = config.getDefaultValidationTrigger(); + } /** * Subscribe to controller validate and reset events. These events occur when the diff --git a/test/validation-controller-factory.ts b/test/validation-controller-factory.ts index 0c6ca977..c5802fec 100644 --- a/test/validation-controller-factory.ts +++ b/test/validation-controller-factory.ts @@ -1,22 +1,28 @@ -import { Container, Optional } from 'aurelia-dependency-injection'; -import { - ValidationControllerFactory, - ValidationController, - Validator -} from '../src/aurelia-validation'; - -describe('ValidationControllerFactory', () => { - it('createForCurrentScope', () => { - const container = new Container(); - const standardValidator = {}; - container.registerInstance(Validator, standardValidator); - const childContainer = container.createChild(); - const factory = childContainer.get(ValidationControllerFactory); - const controller = factory.createForCurrentScope(); - expect(controller.validator).toBe(standardValidator); - expect(container.get(Optional.of(ValidationController))).toBe(null); - expect(childContainer.get(Optional.of(ValidationController))).toBe(controller); - const customValidator = {}; - expect(factory.createForCurrentScope(customValidator).validator).toBe(customValidator); - }); -}); +import { Container, Optional } from 'aurelia-dependency-injection'; +import { + AureliaValidationConfiguration, + ValidationControllerFactory, + ValidationController, + Validator, + validateTrigger +} from '../src/aurelia-validation'; + +describe('ValidationControllerFactory', () => { + it('createForCurrentScope', () => { + const container = new Container(); + const standardValidator = {}; + container.registerInstance(Validator, standardValidator); + const config = new AureliaValidationConfiguration(); + config.defaultValidationTrigger(validateTrigger.manual); + container.registerInstance(AureliaValidationConfiguration, config); + const childContainer = container.createChild(); + const factory = childContainer.get(ValidationControllerFactory); + const controller = factory.createForCurrentScope(); + expect(controller.validator).toBe(standardValidator); + expect(controller.validateTrigger).toBe(validateTrigger.manual); + expect(container.get(Optional.of(ValidationController))).toBe(null); + expect(childContainer.get(Optional.of(ValidationController))).toBe(controller); + const customValidator = {}; + expect(factory.createForCurrentScope(customValidator).validator).toBe(customValidator); + }); +}); From a52f4c403bb68ed895fd0b7a3ea217c67ce22e2d Mon Sep 17 00:00:00 2001 From: Romke van der Meulen Date: Fri, 1 Nov 2019 12:01:39 +0100 Subject: [PATCH 2/4] feat(config): make config constructor param optional and place default trigger in static property --- src/config.ts | 4 +++- src/validation-controller.ts | 6 ++++-- test/validation-controller.ts | 22 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 test/validation-controller.ts diff --git a/src/config.ts b/src/config.ts index cde94c3c..edf3b794 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,8 +7,10 @@ import { validateTrigger } from './validate-trigger'; * Aurelia Validation Configuration API */ export class AureliaValidationConfiguration { + public static DEFAULT_VALIDATION_TRIGGER = validateTrigger.blur; + private validatorType: { new (...args: any[]): Validator } = StandardValidator; - private validationTrigger = validateTrigger.blur; + private validationTrigger = AureliaValidationConfiguration.DEFAULT_VALIDATION_TRIGGER; /** * Use a custom Validator implementation. diff --git a/src/validation-controller.ts b/src/validation-controller.ts index 941ed8f0..5f20840e 100644 --- a/src/validation-controller.ts +++ b/src/validation-controller.ts @@ -58,9 +58,11 @@ export class ValidationController { constructor( private validator: Validator, private propertyParser: PropertyAccessorParser, - config: AureliaValidationConfiguration, + config?: AureliaValidationConfiguration, ) { - this.validateTrigger = config.getDefaultValidationTrigger(); + this.validateTrigger = config instanceof AureliaValidationConfiguration + ? config.getDefaultValidationTrigger() + : AureliaValidationConfiguration.DEFAULT_VALIDATION_TRIGGER; } /** diff --git a/test/validation-controller.ts b/test/validation-controller.ts new file mode 100644 index 00000000..f2ac13eb --- /dev/null +++ b/test/validation-controller.ts @@ -0,0 +1,22 @@ +import { + AureliaValidationConfiguration, + PropertyAccessorParser, + ValidationController, + Validator, + validateTrigger, +} from '../src/aurelia-validation'; + +describe('ValidationController', () => { + it('takes a validator, a PropertyAccessorParser, and optional config', () => { + const validator = {} as any as Validator; + const parser = {} as any as PropertyAccessorParser; + const controller = new ValidationController(validator, parser); + expect(controller.validateTrigger).toBe(AureliaValidationConfiguration.DEFAULT_VALIDATION_TRIGGER); + + const trigger = validateTrigger.changeOrBlur; + const config = new AureliaValidationConfiguration(); + config.defaultValidationTrigger(trigger); + const controllerWithConfig = new ValidationController(validator, parser, config); + expect(controllerWithConfig.validateTrigger).toBe(trigger); + }); +}); From c4e5fe29e2a9bcd11cfdaba0f70050ef9c894be6 Mon Sep 17 00:00:00 2001 From: Romke van der Meulen Date: Fri, 22 Nov 2019 10:44:27 +0100 Subject: [PATCH 3/4] feat(config): rename global config class --- src/aurelia-validation.ts | 6 +++--- src/config.ts | 6 +++--- src/validation-controller-factory.ts | 4 ++-- src/validation-controller.ts | 10 +++++----- test/validation-controller-factory.ts | 6 +++--- test/validation-controller.ts | 6 +++--- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/aurelia-validation.ts b/src/aurelia-validation.ts index 18ff40ac..ec205115 100644 --- a/src/aurelia-validation.ts +++ b/src/aurelia-validation.ts @@ -27,7 +27,7 @@ export * from './implementation/validation-rules'; // Configuration import { Container } from 'aurelia-dependency-injection'; -import { AureliaValidationConfiguration } from './config'; +import { GlobalValidationConfiguration } from './config'; import { ValidationMessageParser } from './implementation/validation-message-parser'; import { PropertyAccessorParser } from './property-accessor-parser'; import { ValidationRules } from './implementation/validation-rules'; @@ -47,7 +47,7 @@ import { ValidationRendererCustomAttribute } from './validation-renderer-custom- export function configure( // tslint:disable-next-line:ban-types frameworkConfig: { container: Container, globalResources?: (...resources: any[]) => any }, - callback?: (config: AureliaValidationConfiguration) => void + callback?: (config: GlobalValidationConfiguration) => void ) { // the fluent rule definition API needs the parser to translate messages // to interpolation expressions. @@ -56,7 +56,7 @@ export function configure( ValidationRules.initialize(messageParser, propertyParser); // configure... - const config = new AureliaValidationConfiguration(); + const config = new GlobalValidationConfiguration(); if (callback instanceof Function) { callback(config); } diff --git a/src/config.ts b/src/config.ts index edf3b794..6b90005e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,11 +6,11 @@ import { validateTrigger } from './validate-trigger'; /** * Aurelia Validation Configuration API */ -export class AureliaValidationConfiguration { +export class GlobalValidationConfiguration { public static DEFAULT_VALIDATION_TRIGGER = validateTrigger.blur; private validatorType: { new (...args: any[]): Validator } = StandardValidator; - private validationTrigger = AureliaValidationConfiguration.DEFAULT_VALIDATION_TRIGGER; + private validationTrigger = GlobalValidationConfiguration.DEFAULT_VALIDATION_TRIGGER; /** * Use a custom Validator implementation. @@ -33,6 +33,6 @@ export class AureliaValidationConfiguration { public apply(container: Container) { const validator = container.get(this.validatorType); container.registerInstance(Validator, validator); - container.registerInstance(AureliaValidationConfiguration, this); + container.registerInstance(GlobalValidationConfiguration, this); } } diff --git a/src/validation-controller-factory.ts b/src/validation-controller-factory.ts index 5d93b0f4..3dff5177 100644 --- a/src/validation-controller-factory.ts +++ b/src/validation-controller-factory.ts @@ -1,5 +1,5 @@ import { Container } from 'aurelia-dependency-injection'; -import { AureliaValidationConfiguration } from './config'; +import { GlobalValidationConfiguration } from './config'; import { ValidationController } from './validation-controller'; import { Validator } from './validator'; import { PropertyAccessorParser } from './property-accessor-parser'; @@ -22,7 +22,7 @@ export class ValidationControllerFactory { validator = this.container.get(Validator) as Validator; } const propertyParser = this.container.get(PropertyAccessorParser) as PropertyAccessorParser; - const config = this.container.get(AureliaValidationConfiguration) as AureliaValidationConfiguration; + const config = this.container.get(GlobalValidationConfiguration) as GlobalValidationConfiguration; return new ValidationController(validator, propertyParser, config); } diff --git a/src/validation-controller.ts b/src/validation-controller.ts index 5f20840e..42657778 100644 --- a/src/validation-controller.ts +++ b/src/validation-controller.ts @@ -1,5 +1,5 @@ import { Binding, Expression } from 'aurelia-binding'; -import { AureliaValidationConfiguration } from './config'; +import { GlobalValidationConfiguration } from './config'; import { Validator } from './validator'; import { validateTrigger } from './validate-trigger'; import { getPropertyInfo } from './property-info'; @@ -16,7 +16,7 @@ import { ValidateEvent } from './validate-event'; * Exposes the current list of validation results for binding purposes. */ export class ValidationController { - public static inject = [Validator, PropertyAccessorParser, AureliaValidationConfiguration]; + public static inject = [Validator, PropertyAccessorParser, GlobalValidationConfiguration]; // Registered bindings (via the validate binding behavior) private bindings = new Map(); @@ -58,11 +58,11 @@ export class ValidationController { constructor( private validator: Validator, private propertyParser: PropertyAccessorParser, - config?: AureliaValidationConfiguration, + config?: GlobalValidationConfiguration, ) { - this.validateTrigger = config instanceof AureliaValidationConfiguration + this.validateTrigger = config instanceof GlobalValidationConfiguration ? config.getDefaultValidationTrigger() - : AureliaValidationConfiguration.DEFAULT_VALIDATION_TRIGGER; + : GlobalValidationConfiguration.DEFAULT_VALIDATION_TRIGGER; } /** diff --git a/test/validation-controller-factory.ts b/test/validation-controller-factory.ts index c5802fec..d74d6af9 100644 --- a/test/validation-controller-factory.ts +++ b/test/validation-controller-factory.ts @@ -1,6 +1,6 @@ import { Container, Optional } from 'aurelia-dependency-injection'; import { - AureliaValidationConfiguration, + GlobalValidationConfiguration, ValidationControllerFactory, ValidationController, Validator, @@ -12,9 +12,9 @@ describe('ValidationControllerFactory', () => { const container = new Container(); const standardValidator = {}; container.registerInstance(Validator, standardValidator); - const config = new AureliaValidationConfiguration(); + const config = new GlobalValidationConfiguration(); config.defaultValidationTrigger(validateTrigger.manual); - container.registerInstance(AureliaValidationConfiguration, config); + container.registerInstance(GlobalValidationConfiguration, config); const childContainer = container.createChild(); const factory = childContainer.get(ValidationControllerFactory); const controller = factory.createForCurrentScope(); diff --git a/test/validation-controller.ts b/test/validation-controller.ts index f2ac13eb..d1c20c97 100644 --- a/test/validation-controller.ts +++ b/test/validation-controller.ts @@ -1,5 +1,5 @@ import { - AureliaValidationConfiguration, + GlobalValidationConfiguration, PropertyAccessorParser, ValidationController, Validator, @@ -11,10 +11,10 @@ describe('ValidationController', () => { const validator = {} as any as Validator; const parser = {} as any as PropertyAccessorParser; const controller = new ValidationController(validator, parser); - expect(controller.validateTrigger).toBe(AureliaValidationConfiguration.DEFAULT_VALIDATION_TRIGGER); + expect(controller.validateTrigger).toBe(GlobalValidationConfiguration.DEFAULT_VALIDATION_TRIGGER); const trigger = validateTrigger.changeOrBlur; - const config = new AureliaValidationConfiguration(); + const config = new GlobalValidationConfiguration(); config.defaultValidationTrigger(trigger); const controllerWithConfig = new ValidationController(validator, parser, config); expect(controllerWithConfig.validateTrigger).toBe(trigger); From bd118a61c9cb283cbb9db36712660a0362f5994c Mon Sep 17 00:00:00 2001 From: Romke van der Meulen Date: Fri, 22 Nov 2019 14:19:29 +0100 Subject: [PATCH 4/4] feat(config): make the setters chainable --- src/config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config.ts b/src/config.ts index 6b90005e..934d4377 100644 --- a/src/config.ts +++ b/src/config.ts @@ -17,10 +17,12 @@ export class GlobalValidationConfiguration { */ public customValidator(type: { new (...args: any[]): Validator }) { this.validatorType = type; + return this; } public defaultValidationTrigger(trigger: validateTrigger) { this.validationTrigger = trigger; + return this; } public getDefaultValidationTrigger() {