diff --git a/knockout/knockout.d.ts b/knockout/knockout.d.ts index 5784112f8..8fc87e98d 100644 --- a/knockout/knockout.d.ts +++ b/knockout/knockout.d.ts @@ -557,7 +557,13 @@ interface KnockoutBindingProvider { } interface KnockoutComponents { - register(componentName: string, definition: KnockoutComponentDefinition): void; + // overloads for register method: + register(componentName: string, config: KnockoutComponentRegister): void; + register(componentName: string, config: KnockoutComponentRegisterStringTemplate): void; + register(componentName: string, config: KnockoutComponentRegisterFnViewModel): void; + register(componentName: string, config: KnockoutComponentRegisterStringTemplateFnViewModel): void; + register(componentName: string, config: KnockoutComponentRegisterAMD): void; + isRegistered(componentName: string): boolean; unregister(componentName: string): void; get(componentName: string, callback: (definition: KnockoutComponentDefinition) => void): void; @@ -567,6 +573,50 @@ interface KnockoutComponents { getComponentNameForNode(node: Node): string; } +/* interfaces for register overloads*/ + +interface KnockoutComponentRegister { + template: KnockoutComponentTemplate; + viewModel?: KnockoutComponentConfigViewModel; +} + +interface KnockoutComponentRegisterAMD { + // load self-describing module using AMD module name + require: string; +} + +interface KnockoutComponentRegisterFnViewModel { + template: KnockoutComponentTemplate; + viewModel?: (params: any) => any; +} + +interface KnockoutComponentRegisterStringTemplate { + template: string; + viewModel?: KnockoutComponentConfigViewModel; +} + +interface KnockoutComponentRegisterStringTemplateFnViewModel { + template: string; + viewModel?: (params: any) => any; +} + +interface KnockoutComponentConfigViewModel { + instance?: any; + createViewModel? (params?: any, componentInfo?: KnockoutComponentInfo): any; + require?: string; +} + +interface KnockoutComponentTemplate { + // specify element id (string) or a node + element?: any; + // AMD module load + require?: string; +} + +interface KnockoutComponentInfo { + element: any; +} +/* end register overloads */ interface KnockoutComponentDefinition { template: Node[]; createViewModel?(params: any, options: { element: Node; }): any; diff --git a/knockout/tests/knockout-tests.ts b/knockout/tests/knockout-tests.ts index 6d4c9e25d..82b5aa25c 100644 --- a/knockout/tests/knockout-tests.ts +++ b/knockout/tests/knockout-tests.ts @@ -602,4 +602,49 @@ function test_allBindingsAccessor() { var fnAccessorBinding = allBindingsAccessor().myBindingName; } }; +} + +function test_Components() { + + function test_Register() { + // test all possible ko.components.register() overloads + var nodeArray = [new Node, new Node]; + var singleNode = new Node; + + // ------- string-templates with different viewmodel overloads: + + // string template and inline function (commonly used in examples) + ko.components.register("name", { template: "string-template", viewModel: function (params) { return null; } }); + + // string template and instance vm + ko.components.register("name", { template: "string-template", viewModel: { instance: null } }); + + // string template and createViewModel factory method + ko.components.register("name", { template: "string-template", viewModel: { createViewModel: function (params: any, componentInfo: KnockoutComponentInfo) { return null; } } }); + + // string template and require module vm + ko.components.register("name", { template: "string-template", viewModel: { require: "module" } }); + + // ------- non-string templates + + // viewmodel as function and four types of template + ko.components.register("name", { template: { element: "elementID" }, viewModel: function (params) { return null; } }); + // Node template for element and inline function (commonly used in examples) + ko.components.register("name", { template: { element: singleNode }, viewModel: function (params) { return null; } }); + // object template for element and inline function (commonly used in examples) + ko.components.register("name", { template: nodeArray, viewModel: function (params) { return null; } }); + // object template for element and inline function (commonly used in examples) + ko.components.register("name", { template: { require: "module" }, viewModel: function (params) { return null; } }); + + // viewmodel as object, and four types of non-string tempalte + ko.components.register("name", { template: { element: "elementID" }, viewModel: { instance: null } }); + // Node template for element and inline function (commonly used in examples) + ko.components.register("name", { template: { element: singleNode }, viewModel: { instance: null } }); + // object template for element and inline function (commonly used in examples) + ko.components.register("name", { template: nodeArray, viewModel: { instance: null } }); + // object template for element and inline function (commonly used in examples) + ko.components.register("name", { template: { require: "module" }, viewModel: { instance: null } }); + + // + } } \ No newline at end of file diff --git a/valerie/valerie-tests.ts b/valerie/valerie-tests.ts index bf9ce7880..b33932e29 100644 --- a/valerie/valerie-tests.ts +++ b/valerie/valerie-tests.ts @@ -285,4 +285,51 @@ function RuleTests() { .rule(() => { return anyValue; }) .end(); -} \ No newline at end of file +} + +function ModelValidation() { + + var model = {}; + + var validatedModel = valerie.validatableModel(model) + .validateAll() + .end(); + +} + +function UtilsStaticTests() { + + var t1 = valerie.utils.asArray(1); + var t2 = valerie.utils.asArray([1,2]); + + var t3 = valerie.utils.asFunction(1); + var t4 = valerie.utils.asFunction(() => { return 1; }); + + var t5 = valerie.utils.isArray([1, 2]); + var t5 = valerie.utils.isArrayOrObject(1); + var t6 = valerie.utils.isFunction("x"); + var t7 = valerie.utils.isMissing(null); + var t8 = valerie.utils.isObject({}); + var t9 = valerie.utils.isString("test"); + + var opts: Valerie.ValidationOptions = {}; // all values are optional + var t10 = valerie.utils.mergeOptions(opts, opts); +} + +function ValidationResultStaticTests() { + + var t1 = valerie.ValidationResult.passedInstance; + + var t2 = valerie.ValidationResult.createFailedResult("message"); + +} + +function ValidationStateStaticTests() { + + var t1 = valerie.validationState.findIn({}); + var t2 = valerie.validationState.getFor({}); + var t3 = valerie.validationState.has({}); + + var state = {}; + var t4 = valerie.validationState.setFor({}, state); +} diff --git a/valerie/valerie.d.ts b/valerie/valerie.d.ts index 847e0a7a0..abe5aea28 100644 --- a/valerie/valerie.d.ts +++ b/valerie/valerie.d.ts @@ -7,7 +7,10 @@ /** * - * Extensions to KO functions to provide validation + * Extensions to KO functions to provide validation + * + * Version 1.2 - added more static methods to valerie object + * */ interface KnockoutObservable { // starts validation for observable @@ -23,7 +26,6 @@ interface KnockoutObservableArray { validate(validationOptions?: Valerie.ValidationOptions): Valerie.PropertyValidationState>; } - interface KnockoutObservableArrayFunctions { /** * Creates and sets a model validation state on a Knockout observable array.
@@ -198,8 +200,6 @@ interface KnockoutBindingHandlers { visibleWhenValid: KnockoutBindingHandler; } - - // // root valerie namespace - static methods // @@ -208,12 +208,10 @@ declare var valerie: Valerie.Static; // additional types for Valerie (all inside this namespace) declare module Valerie { - // // Static methods on valerie namespace // interface Static { - /** * Maps a source model to a destination model, including only applicable properties * @param {Object|Array} sourceModel the source model @@ -248,9 +246,78 @@ declare module Valerie { // (value should be observable or computed) validatableProperty(value: T, options?: ValidationOptions): PropertyValidationState; + // Validation result class + ValidationResult: ValidationResultStatic; + // additional namespaces for static methods: + converters: ConvertersStatic; + + /* + //TODO: additional namespaces/statics not yet used + dom: DomStatic; + formatting: FormattingStatic; + koBindingsHelper: KoBindingsHelperStatic; + koExtras: KoExtrasStatic; + rules: RulesStatic; + */ + + utils: UtilsStatic; + validationState: ValidationState; + + } + + interface ValidationResultStatic { + + passedInstance: ValidationResult; + + // static method to create validatio failed message + createFailedResult(message: string): ValidationResult; + } + + // Contains converters, always singletons. + interface ConvertersStatic { + + //TODO: other converters to be added + + passThrough: Valerie.IConverter; + } + + + interface UtilsStatic { + + // Creates a function that returns the given value as an array of one item, or simply returns the given value if it is already an array. + asArray(value: any): any[]; + + // Creates a function that returns the given value, or simply returns the given value if it is already a function + asFunction(value: T): () => T; + asFunction(fn: () => T): () => T; + + // Tests whether the given value is an array + isArray(value: any): boolean; + + // Tests whether the given value is an array or object. + isArrayOrObject(value: any): boolean; + + // Tests whether the given value is a function. + isFunction(value: any): boolean; + + // Tests whether the given value is "missing".undefined, null, an empty string or an empty array are considered to be "missing". + isMissing(value: any): boolean; + + // Tests whether the given value is an object. + isObject(value: any): boolean; + + // Tests whether the give value is a string. + isString(value: any): boolean; + + //Merges the given default options with the given options. + // - either parameter can be omitted and a clone of the other parameter will be returned + // - the merge is shallow + // - array properties are shallow cloned + mergeOptions(defaultOptions: ValidationOptions, options:any): ValidationOptions; + } // callback interface (see mapModel above) @@ -263,10 +330,175 @@ declare module Valerie { // ctor new: (model: any, options?: ModelValidationStateOptions) => ModelValidationState; - addValidationStates(validationStateOrStates: any): void; - model: any; options?: ModelValidationStateOptions + + // methods + + /** + * Adds validation states to this validation state.
+ * [fluent] + * @name valerie.ModelValidationState#addValidationStates + * @fluent + * @param {object|array.} validationStateOrStates the validation states to add + * @return {valerie.ModelValidationState} + */ + addValidationStates(validationStateOrStates: any): ModelValidationState; + + /** + * Sets the value or function used to determine if the model is applicable.
+ * [fluent] + * @name valerie.ModelValidationState#applicable + * @fluent + * @param {boolean|function} [valueOrFunction = true] the value or function to use + * @return {valerie.ModelValidationState} + */ + applicable(valueOrFunction: any): ModelValidationState; + + /** + * Clears the static summary of validation states that are in a failure state.
+ * [fluent] + * @name valerie.ModelValidationState#clearSummary + * @fluent + * @param {boolean} [clearSubModelSummaries = false] whether to clear the static summaries for sub-models + * @return {valerie.ModelValidationState} + */ + clearSummary(valueOrFunction: any): ModelValidationState; + + /*** + * Gets whether the model has failed validation. + * @return {boolean} + */ + failed(): boolean; + + /*** + * Gets the validation states that belong to the model that are in a failure state. + * @return {Valerie.IValidationState[]} + */ + failedStates(): Valerie.IValidationState[]; + + /*** + * Gets the name of the model. + * @return {string} + */ + getName(): string; + + isApplicable(): boolean; + message(): string; + passed(): boolean; + + /*** + * Gets or sets whether the computation that updates the validation result has been paused. + * @param {boolean} [value = false] true if the computation should be paused, false if the computation should not be paused + * @return {boolean} true if computation is paused, false otherwise + */ + paused(value: boolean): boolean; + + pending(): boolean; + + pendingStates(): IValidationState[]; + + refresh(): void; + + result(): ValidationResult; + + summary(): summaryItem[] + + /*** + * Gets or sets whether the model has been 'touched' by user action + */ + touched(value: boolean): boolean; + + + validationStates(): IValidationState[]; + + /** + * Includes any validation failures for this model in a validation summary.
+ * [fluent] + * @fluent + * @return {valerie.ModelValidationState} + */ + includeInSummary(): ModelValidationState; + + /** + * Sets the value or function used to determine the name of the model.
+ * [fluent] + * @fluent + * @param {string|function} valueOrFunction the value or function to use + * @return {valerie.ModelValidationState} + */ + name(valueOrFunction: any): ModelValidationState; + + /** + * Removes validation states.
+ * [fluent] + * @fluent + * @param {object|array.} validationStateOrStates the validation states to remove + * @return {valerie.ModelValidationState} + */ + removeValidationStates(validationStateOrStates: any): ModelValidationState; + + /** + * Stops validating the given sub-model by adding the validation state that belongs to it. + * @param {*} validatableSubModel the sub - model to start validating + * @return {valerie.ModelValidationState } + */ + startValidatingSubModel(validatableSubModel: any): ModelValidationState; + + /** + * Stops validating the given sub-model by removing the validation state that belongs to it. + * @param {*} validatableSubModel the sub-model to stop validating + * @return {valerie.ModelValidationState} + */ + stopValidatingSubModel(validatableSubModel: any): ModelValidationState; + + /** + * Updates the static summary of validation states that are in a failure state.
+ * [fluent] + * @fluent + * @param {boolean} [updateSubModelSummaries = false] whether to update the static summaries for sub-models + * @return {valerie.ModelValidationState} + */ + updateSummary(updateSubModelSummaries: boolean): ModelValidationState; + + /** + * Adds the validation states for all the descendant properties and sub-models that belong to the model.
+ * [fluent] + * @fluent + * @return {valerie.ModelValidationState} + */ + validateAll(): ModelValidationState; + + /** + * Adds the validation states for all the descendant properties that belong to the model.
+ * [fluent] + * @fluent + * @return {valerie.ModelValidationState} + */ + validateAllProperties(): ModelValidationState; + + /** + * Adds the validation states for all the child properties that belong to the model.
+ * [fluent] + * @fluent + * @return {valerie.ModelValidationState} + */ + validateChildProperties(): ModelValidationState; + + /** + * Adds the validation states for all the child properties and sub-models that belong to the model.
+ * [fluent] + * @fluent + * @return {valerie.ModelValidationState} + */ + validateChildPropertiesAndSubModels(): ModelValidationState; + + + /** + * Ends a chain of fluent method calls on this model validation state. + * @return {function} the model the validation state is for + */ + end(): any; } // Construction options for a model validation state. @@ -282,7 +514,6 @@ declare module Valerie { // PropertyValidationState // interface PropertyValidationState { - // properties: // the observable or computed the validation state is for @@ -310,12 +541,12 @@ declare module Valerie { during(earliest: () => Date, latest: Date, options?: ValidationOptions): PropertyValidationState; // dateFN + date during(earliest: Date, latest: () => Date, options?: ValidationOptions): PropertyValidationState; // date + dateFN during(earliest: () => Date, latest: () => Date, options?: ValidationOptions): PropertyValidationState; // dateFN + dateFN - earliest(earliest: Date, options?: ValidationOptions): PropertyValidationState; // date value + earliest(earliest: Date, options?: ValidationOptions): PropertyValidationState; // date value earliest(earliest: () => Date, options?: ValidationOptions): PropertyValidationState; // date function email(): PropertyValidationState; entryFormat(format: string): PropertyValidationState; excludeFromSummary(): PropertyValidationState; - expression(regularExpression: RegExp, options?: ValidationOptions): PropertyValidationState; // regex + expression(regularExpression: RegExp, options?: ValidationOptions): PropertyValidationState; // regex expression(regularExpressionString: string, options?: ValidationOptions): PropertyValidationState; // regex string float(options?: ValidationOptions): PropertyValidationState; integer(options?: ValidationOptions): PropertyValidationState; @@ -377,7 +608,6 @@ declare module Valerie { touched(): boolean; // get touched state touched(value: boolean): boolean; // set touched state result(): ValidationResult; - } interface ValidationResult { @@ -387,10 +617,6 @@ declare module Valerie { pending: boolean; //true if the activity hasn't yet completed message: string; //a message from the activity new: (state: any, message?: string) => ValidationResult; - - //TODO: not added static members/methods - createFailedResult(message: string): ValidationResult; - } interface IRule { @@ -411,7 +637,7 @@ declare module Valerie { } interface ValidatableModel { - name: (value:string) => PropertyValidationState; + name: (value: string) => PropertyValidationState; // return original observableArray end: () => T; @@ -438,7 +664,6 @@ declare module Valerie { // A helper for parsing and formatting numeric values. interface NumericHelper { - // Adds thousands separators to the given numeric string. addThousandsSeparator(numericString: string): string; @@ -468,13 +693,10 @@ declare module Valerie { // Unformats a numeric string; removes currency signs, thousands separators and normalises decimal separators. unformat(numericString: string): string; - } - interface ValidationState { - - // Finds and returns the validation states + // Finds and returns the validation states findIn(model: any, includeSubModels?: boolean, recurse?: boolean, @@ -486,18 +708,20 @@ declare module Valerie { // nforms if the given model, observable or computed has a validation state. has(modelOrObservableOrComputed: any): boolean; - // Sets the validation state for the given model, observable or computed. setFor(modelOrObservableOrComputed: any, state: IValidationState): void; + } + interface summaryItem { + name: string; + message: string; } } declare module Valerie.Rules { - /* Todo: add classes in valerie.rules namespace */ -} \ No newline at end of file +}