POC for single message based validation

This commit is contained in:
Niels Lyngsø
2024-08-08 20:33:12 +02:00
parent 62fa41a5cd
commit cd84ff9b6d
2 changed files with 59 additions and 18 deletions

View File

@@ -13,8 +13,8 @@ type UmbNativeFormControlElement = Pick<
* https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
* */
type FlagTypes =
| 'badInput'
| 'customError'
| 'badInput'
| 'patternMismatch'
| 'rangeOverflow'
| 'rangeUnderflow'
@@ -23,9 +23,21 @@ type FlagTypes =
| 'tooShort'
| 'typeMismatch'
| 'valueMissing'
| 'badInput'
| 'valid';
const WeightedErrorFlagTypes = [
'customError',
'badInput',
'patternMismatch',
'rangeOverflow',
'rangeUnderflow',
'stepMismatch',
'tooLong',
'tooShort',
'typeMismatch',
'valueMissing',
];
// Acceptable as an internal interface/type, BUT if exposed externally this should be turned into a public interface in a separate file.
export interface UmbFormControlValidatorConfig {
flagKey: FlagTypes;
@@ -222,6 +234,11 @@ export function UmbFormControlMixin<
checkMethod: checkMethod,
} satisfies UmbFormControlValidatorConfig;
this.#validators.push(validator);
// Sort validators based on the WeightedErrorFlagTypes order. [NL]
this.#validators.sort((a, b) => {
// This could easily be extended with a weight set on the validator object itself. [NL]
return WeightedErrorFlagTypes.indexOf(a.flagKey) - WeightedErrorFlagTypes.indexOf(b.flagKey);
});
return validator;
}
@@ -291,29 +308,38 @@ export function UmbFormControlMixin<
*/
protected _runValidators() {
this.#validity = {};
const messages: Set<string> = new Set();
//const messages: Set<string> = new Set();
let message: string | undefined = undefined;
let innerFormControlEl: UmbNativeFormControlElement | undefined = undefined;
// Loop through inner native form controls to adapt their validityState. [NL]
this.#formCtrlElements.forEach((formCtrlEl) => {
let key: keyof ValidityState;
for (key in formCtrlEl.validity) {
if (key !== 'valid' && formCtrlEl.validity[key]) {
this.#validity[key] = true;
messages.add(formCtrlEl.validationMessage);
innerFormControlEl ??= formCtrlEl;
}
}
});
// Loop through custom validators, currently its intentional to have them overwritten native validity. but might need to be reconsidered (This current way enables to overwrite with custom messages) [NL]
this.#validators.forEach((validator) => {
this.#validators.some((validator) => {
if (validator.checkMethod()) {
this.#validity[validator.flagKey] = true;
messages.add(validator.getMessageMethod());
//messages.add(validator.getMessageMethod());
message = validator.getMessageMethod();
return true;
}
return false;
});
if (message) {
// Loop through inner native form controls to adapt their validityState. [NL]
this.#formCtrlElements.some((formCtrlEl) => {
let key: keyof ValidityState;
for (key in formCtrlEl.validity) {
if (key !== 'valid' && formCtrlEl.validity[key]) {
this.#validity[key] = true;
//messages.add(formCtrlEl.validationMessage);
message = formCtrlEl.validationMessage;
innerFormControlEl ??= formCtrlEl;
return true;
}
}
return false;
});
}
const hasError = Object.values(this.#validity).includes(true);
// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState#valid
@@ -323,7 +349,8 @@ export function UmbFormControlMixin<
this._internals.setValidity(
this.#validity,
// Turn messages into an array and join them with a comma. [NL]:
[...messages].join(', '),
//[...messages].join(', '),
message,
innerFormControlEl ?? this.getFormElement() ?? undefined,
);

View File

@@ -55,6 +55,20 @@ export class UmbPropertyEditorUITextBoxElement
this._placeholder = config?.getValueByAlias('placeholder');
}
constructor() {
super();
this.addValidator(
'tooShort',
() => 'custom too short msg',
() => String(this.value).length < 10,
);
this.addValidator(
'valueMissing',
() => 'custom valueMissing msg',
() => this.value === undefined && this.value === '',
);
}
protected override firstUpdated(): void {
this.addFormControlElement(this.shadowRoot!.querySelector('uui-input')!);
}