This is the syntax to build the ValueHostConfig (with all of its children) quickly
and succinctly. It is a fluent syntax that allows the developer to chain operations.
These tools are used in the Builder API (ValidationManagerConfigBuilder class),
which is what the developer creates with the ValidatorManagerConfig that they are constructing.
Similarly, these tools are used in the Modifier API (ValidationManagerConfigModifier class),
which is what the developer uses to modify the configuration after ValidationManager is created.
Effectively ValidationManagerConfigBuilder and ValidationManagerConfigModifier are wrapper classes
around ValueHostsManagerStartFluent.
With the following, assume 'let builder = new ValidationManagerConfigBuilder(vmConfig)'.
The user will start the fluent syntax with builder.input(), builder.property(),
builder.static(), or builder.calc().
Those will setup the configs for each type of ValueHost
taking advantage of intellisense to expose the available properties
of the config, which may be a subset of the original.
Each condition class will define its fluent method based on its ConditionType name ("requireText", "regExp", etc).
They will use some TypeScript Declaration Merging magic to make their
class appear to be part of FluentValidatorBuilder and FluentConditionBuilder, classes that connect
the conditions to the InputValueHostConfig or EvaluateChildConditionResultsConfig.
ValidationManagerStartFluent - Class that starts a fluent chain. Its methods start InputValueHost (input()),
PropertyValueHost (property()), StaticValueHost (static()), CalcValueHost (calc()) and a collection of Conditions (conditions()).
FluentValidatorBuilder - Class that supplies Conditions and Validators
to the preceding InputValueHost. It is returned by builder.input() and property() and each chained object that follows.
FluentConditionBuilder - Class that supplies Conditions to Conditions based upon EvaluateChildConditionResultsConfig:
AllMatchCondition, AnyMatchCondition, and CountMatchesCondition. It is created
by builder.conditions()
Create two functions to support chaining to builder.input/property() and builder.conditions().
They are not exported, as they are used to modify the prototypes of other classes.
declaremodule"@plblum/jivs-engine/build/ValueHosts/fluent" { exportinterfaceFluentValidatorBuilder { // same definition as the actual function, except use the name the user should enter in chaining regExp(expression: RegExp | string, ignoreCase?: boolean | null, conditionConfig?: FluentRegExpConditionConfig | null, errorMessage?: string | null, validatorParameters : FluentRegExpConditionConfig) : FluentValidatorBuilder } exportinterfaceFluentConditionBuilder { // same definition as the actual function, except use the name the user should enter in chaining regExp(expression: RegExp | string, ignoreCase?: boolean | null, conditionConfig?: FluentRegExpConditionConfig) : FluentConditionBuilder } } FluentValidatorBuilder.prototype.regExp = regExp_forValidator; FluentConditionBuilder.prototype.regExp = regExp_forConditions;
This is the syntax to build the ValueHostConfig (with all of its children) quickly and succinctly. It is a fluent syntax that allows the developer to chain operations.
These tools are used in the Builder API (ValidationManagerConfigBuilder class), which is what the developer creates with the ValidatorManagerConfig that they are constructing. Similarly, these tools are used in the Modifier API (ValidationManagerConfigModifier class), which is what the developer uses to modify the configuration after ValidationManager is created. Effectively ValidationManagerConfigBuilder and ValidationManagerConfigModifier are wrapper classes around ValueHostsManagerStartFluent.
With the following, assume 'let builder = new ValidationManagerConfigBuilder(vmConfig)'.
The user will start the fluent syntax with builder.input(), builder.property(), builder.static(), or builder.calc(). Those will setup the configs for each type of ValueHost taking advantage of intellisense to expose the available properties of the config, which may be a subset of the original.
builder.input('valueHostName').[chained validators]
With optional parameters:
builder.input('valueHostName', 'datatype lookup key', { label: 'label' }).[chained validators];
builder.property('valueHostName').[chained validators]
With optional parameters:
builder.property('valueHostName', 'datatype lookup key', { label: 'label' }).[chained validators];
builder.static('valueHostName').[chained functions]
With optional parameters:
builder.static('valueHostName', 'datatype lookup key', { label: 'label' }).[chained builder functions];
builder.calc('valueHostName', 'datatype lookup key', function callback).[chained builder functions];
For example:
How this system works
Each condition class will define its fluent method based on its ConditionType name ("requireText", "regExp", etc). They will use some TypeScript Declaration Merging magic to make their class appear to be part of FluentValidatorBuilder and FluentConditionBuilder, classes that connect the conditions to the InputValueHostConfig or EvaluateChildConditionResultsConfig.
ValidationManagerStartFluent - Class that starts a fluent chain. Its methods start InputValueHost (input()), PropertyValueHost (property()), StaticValueHost (static()), CalcValueHost (calc()) and a collection of Conditions (conditions()).
FluentValidatorBuilder - Class that supplies Conditions and Validators to the preceding InputValueHost. It is returned by builder.input() and property() and each chained object that follows.
FluentConditionBuilder - Class that supplies Conditions to Conditions based upon EvaluateChildConditionResultsConfig: AllMatchCondition, AnyMatchCondition, and CountMatchesCondition. It is created by builder.conditions()
Extending this system with your own fluent functions
Create two functions to support chaining to builder.input/property() and builder.conditions(). They are not exported, as they are used to modify the prototypes of other classes.
Fluent functions should look like this:
Example