JSDocs
This commit is contained in:
@@ -24,9 +24,10 @@ Because each validation issue is presented in the Validation Context as a Messag
|
||||
One benefit of this is that Elements that are removed from screen can still have their validation messages preventing the submission of a dataset.
|
||||
As well Tabs and other navigation can use this to be highlighted, so the user can be guide to the location.
|
||||
|
||||
### Path
|
||||
### Path aka. Data Path
|
||||
|
||||
The Path, points to the location of the model that the message is concerning.
|
||||
The Path also named Data Path, A Path pointing to the related data in the model.
|
||||
A massage uses this to point to the location in the model that the message is concerned.
|
||||
|
||||
The following models headline can be target with this path:
|
||||
|
||||
@@ -91,9 +92,9 @@ This is needed to allow the user to make changes to the data, without loosing th
|
||||
|
||||
## Validation Path Translator
|
||||
|
||||
Validation Path Translator translate Message Paths into a format that works while manipulating the model.
|
||||
This enables the user to retrieve validation messages from the server regarding entries of a list, and then the user can insert more items and still have the validation appearing in the right spots.
|
||||
This would not be possible with index based paths, which is why we translate them into JSON Path Queries.
|
||||
Validation Path Translator translate Message Paths into a format that is independent of the actual current data. But compatible with mutations of that data model.
|
||||
This enables the user to retrieve validation messages from the server, and then the user can insert more items and still have the validation appearing in the right spots.
|
||||
This would not be possible with index based paths, which is why we translate those into JSON Path Queries.
|
||||
|
||||
Such conversation could be from this path:
|
||||
```
|
||||
@@ -104,3 +105,13 @@ To this path:
|
||||
```
|
||||
"$.values.[?(@.alias = 'my-alias')].value"
|
||||
```
|
||||
|
||||
Once this path is converted to use Json Path Queries, the Data can be changed. The concerned entry might get another index. Without that affecting the accuracy of the path.
|
||||
|
||||
### Late registered Path Translators
|
||||
|
||||
Translators can be registered late. This means that a Property Editor that has a complex value structure, can register a Path Translator for its part of the data. Such Translator will appear late because the Property might not be rendered in the users current view, but first when the user navigates there.
|
||||
This is completely fine, as messages can be partly translated and then enhanced by late coming Path Translators.
|
||||
|
||||
This fact enables a property to observe if there is any Message Paths that start with the same path as the Data Path for the Property. In this was a property can know that it contains a Validation Message without the Message Path begin completely translated.
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ function ReplaceStartOfString(path: string, startFrom: string, startTo: string):
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation Context is the core of Validation.
|
||||
* It hosts Validators that has to validate for the context to be valid.
|
||||
* It can also be used as a Validator as part of a parent Validation Context.
|
||||
*/
|
||||
export class UmbValidationContext extends UmbControllerBase implements UmbValidator {
|
||||
// The current provider controller, that is providing this context:
|
||||
#providerCtrl?: UmbContextProviderController<UmbValidationContext, UmbValidationContext, UmbValidationContext>;
|
||||
@@ -47,10 +52,18 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
super(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a path translator to this validation context.
|
||||
* @param translator
|
||||
*/
|
||||
async addTranslator(translator: UmbValidationMessageTranslator) {
|
||||
this.messages.addTranslator(translator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a path translator from this validation context.
|
||||
* @param translator
|
||||
*/
|
||||
async removeTranslator(translator: UmbValidationMessageTranslator) {
|
||||
this.messages.removeTranslator(translator);
|
||||
}
|
||||
@@ -64,11 +77,33 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
this.provideContext(UMB_VALIDATION_CONTEXT, this);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Provide this validation context to a specific controller host.
|
||||
* This can be used to Host a validation context in a Workspace, but provide it on a certain scope, like a specific Workspace View.
|
||||
* @param controllerHost {UmbClassInterface}
|
||||
*/
|
||||
provideAt(controllerHost: UmbClassInterface): void {
|
||||
this.#providerCtrl?.destroy();
|
||||
this.#providerCtrl = controllerHost.provideContext(UMB_VALIDATION_CONTEXT, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a specific data path for this validation context.
|
||||
* This will turn this validation context into a sub-context of the parent validation context.
|
||||
* This means that a two-way binding for messages will be established between the parent and the sub-context.
|
||||
* And it will inherit the Translation Data from its parent.
|
||||
*
|
||||
* messages and data will be localizes accordingly to the given data path.
|
||||
* @param dataPath {string} - The data path to bind this validation context to.
|
||||
* @returns
|
||||
* @example
|
||||
* ```ts
|
||||
* const validationContext = new UmbValidationContext(host);
|
||||
* validationContext.setDataPath("$.values[?(@.alias='my-property')].value");
|
||||
* ```
|
||||
*
|
||||
* A message with the path: '$.values[?(@.alias='my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context.
|
||||
*/
|
||||
setDataPath(dataPath: string): void {
|
||||
if (this.#baseDataPath) {
|
||||
if (this.#baseDataPath === dataPath) return;
|
||||
@@ -106,7 +141,6 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
}
|
||||
this.#parentMessages = msgs;
|
||||
msgs.forEach((msg) => {
|
||||
// TODO: Subtract the base path from the path, so it becomes local to this context:
|
||||
const path = ReplaceStartOfString(msg.path, this.#baseDataPath!, '$');
|
||||
// Notice, the local message uses the same key. [NL]
|
||||
this.messages.addMessage(msg.type, path, msg.body, msg.key);
|
||||
@@ -129,7 +163,6 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
}
|
||||
this.#localMessages = msgs;
|
||||
msgs.forEach((msg) => {
|
||||
// TODO: Prefix the base path from our base path, so it fits in the parent context:
|
||||
// replace this.#baseDataPath (if it starts with it) with $ in the path, so it becomes relative to the parent context
|
||||
const path = ReplaceStartOfString(msg.path, '$', this.#baseDataPath!);
|
||||
// Notice, the parent message uses the same key. [NL]
|
||||
@@ -138,25 +171,24 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
},
|
||||
'observeLocalMessages',
|
||||
);
|
||||
|
||||
// observe if one of the locals got removed.
|
||||
// It can maybe be done with one set of known/gotten parent messages, that then can be used to detect which are removed. Maybe from both sides.
|
||||
|
||||
// Benefits for workspaces:
|
||||
// — The workspace can be validated locally, and then the messages can propagate to parent context. (Do we even want that?)
|
||||
// — The workspace can easier know about its validation state
|
||||
// — Its the only way the sub-workspace can be validated without triggering the whole validation.
|
||||
// - The workspace can inherit messages from parent context... — which is good for Blocks
|
||||
// - The workspace can have its own server messages, that is propagated to parent context.
|
||||
// - The workspace can inherit server messages from parent context... — server validation of a block, that is part of the parent workspace.
|
||||
// - Remove parent messages if they go away again if they gets remove here.
|
||||
}).skipHost();
|
||||
// Notice skipHost ^^, this is because we do not want it to consume it self, as this would be a match for this consumption, instead we will look at the parent and above. [NL]
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if this context is valid.
|
||||
* Notice this does not verify the validity.
|
||||
*/
|
||||
get isValid(): boolean {
|
||||
return this.#isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a validator to this context.
|
||||
* This validator will have to be valid for the context to be valid.
|
||||
* If the context is in validation mode, the validator will be validated immediately.
|
||||
* @param validator { UmbValidator } - The validator to add to this context.
|
||||
*/
|
||||
addValidator(validator: UmbValidator): void {
|
||||
if (this.#validators.includes(validator)) return;
|
||||
this.#validators.push(validator);
|
||||
@@ -166,6 +198,10 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a validator from this context.
|
||||
* @param validator {UmbValidator} - The validator to remove from this context.
|
||||
*/
|
||||
removeValidator(validator: UmbValidator): void {
|
||||
const index = this.#validators.indexOf(validator);
|
||||
if (index !== -1) {
|
||||
@@ -179,7 +215,8 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Validate this context, all the validators of this context will be validated.
|
||||
* Notice its a recursive check meaning sub validation contexts also validates their validators.
|
||||
* @returns succeed {Promise<boolean>} - Returns a promise that resolves to true if the validator succeeded, this depends on the validators and wether forceSucceed is set.
|
||||
*/
|
||||
async validate(): Promise<void> {
|
||||
@@ -206,6 +243,9 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the first invalid element that this context can find.
|
||||
*/
|
||||
focusFirstInvalidElement(): void {
|
||||
const firstInvalid = this.#validators.find((v) => !v.isValid);
|
||||
if (firstInvalid) {
|
||||
@@ -213,6 +253,9 @@ export class UmbValidationContext extends UmbControllerBase implements UmbValida
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the validation state of this context.
|
||||
*/
|
||||
reset(): void {
|
||||
this.#validationMode = false;
|
||||
this.#validators.forEach((v) => v.reset());
|
||||
|
||||
Reference in New Issue
Block a user