fix(validate-mixin): determine required or result validators based on characteristics (#2498)
* fix(validate-mixin): determine if a required validator or result validator has been registered based on characteristics * chore(validate-mixin): create changeset
This commit is contained in:
parent
6d7e6a6487
commit
07b089e80f
3 changed files with 127 additions and 7 deletions
5
.changeset/tall-doors-smoke.md
Normal file
5
.changeset/tall-doors-smoke.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/ui': patch
|
||||
---
|
||||
|
||||
[validate-mixin] determine if a required validator or result validator has been registered based on characteristics
|
||||
|
|
@ -8,11 +8,11 @@ import { AsyncQueue } from '../utils/AsyncQueue.js';
|
|||
import { pascalCase } from '../utils/pascalCase.js';
|
||||
import { SyncUpdatableMixin } from '../utils/SyncUpdatableMixin.js';
|
||||
import { LionValidationFeedback } from './LionValidationFeedback.js';
|
||||
import { ResultValidator as MetaValidator } from './ResultValidator.js';
|
||||
import { Unparseable } from './Unparseable.js';
|
||||
import { Required } from './validators/Required.js';
|
||||
import { FormControlMixin } from '../FormControlMixin.js';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { ResultValidator as MetaValidator } from './ResultValidator.js';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { Validator } from './Validator.js';
|
||||
// TODO: [v1] make all @readOnly => @readonly and actually make sure those values cannot be set
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ export const ValidateMixinImplementation = superclass =>
|
|||
|
||||
/**
|
||||
* Combination of validators provided by Application Developer and the default validators
|
||||
* @type {Validator[]}
|
||||
* @type {(Validator | MetaValidator)[]}
|
||||
* @protected
|
||||
*/
|
||||
get _allValidators() {
|
||||
|
|
@ -480,9 +480,9 @@ export const ValidateMixinImplementation = superclass =>
|
|||
const asyncValidators = /** @type {Validator[]} */ [];
|
||||
|
||||
for (const v of this._allValidators) {
|
||||
if (v instanceof MetaValidator) {
|
||||
metaValidators.push(v);
|
||||
} else if (v instanceof Required) {
|
||||
if (/** @type {MetaValidator} */ (v)?.executeOnResults) {
|
||||
metaValidators.push(/** @type {MetaValidator} */ (v));
|
||||
} else if (/** @type {typeof Validator} */ (v.constructor)?.validatorName === 'Required') {
|
||||
// Required validator was already handled
|
||||
} else if (/** @type {typeof Validator} */ (v.constructor).async) {
|
||||
asyncValidators.push(v);
|
||||
|
|
|
|||
|
|
@ -130,6 +130,121 @@ export function runValidateMixinSuite(customConfig) {
|
|||
expect(el.hasFeedbackFor).to.deep.equal(['error']);
|
||||
});
|
||||
|
||||
it('determines whether the "Required" validator was already handled by judging the validatorName', async () => {
|
||||
class BundledValidator extends EventTarget {
|
||||
static ['_$isValidator$'] = true;
|
||||
|
||||
static validatorName = '';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.type = 'error';
|
||||
}
|
||||
|
||||
get config() {
|
||||
// simplified version of the actual config
|
||||
return {};
|
||||
}
|
||||
|
||||
execute() {
|
||||
// simplified version of the action execution
|
||||
return true;
|
||||
}
|
||||
|
||||
onFormControlConnect() {}
|
||||
|
||||
onFormControlDisconnect() {}
|
||||
|
||||
async _getMessage() {
|
||||
// simplified version of the actual logic
|
||||
return 'You need to enter something.';
|
||||
}
|
||||
}
|
||||
|
||||
class BundledRequired extends BundledValidator {
|
||||
static get validatorName() {
|
||||
return 'Required';
|
||||
}
|
||||
}
|
||||
|
||||
const el = /** @type {ValidateElement} */ (
|
||||
await fixture(html`
|
||||
<${tag}
|
||||
.validators=${[new BundledRequired()]}
|
||||
.modelValue=${'myValue'}
|
||||
>${lightDom}</${tag}>
|
||||
`)
|
||||
);
|
||||
|
||||
expect(el.hasFeedbackFor).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('determines whether the passed Validators are ResultValidators judging by the presence of "executeOnResults"', async () => {
|
||||
class ValidateElementWithSuccessType extends ValidateElement {
|
||||
static get validationTypes() {
|
||||
return ['error', 'success'];
|
||||
}
|
||||
}
|
||||
|
||||
const elTagString = defineCE(ValidateElementWithSuccessType);
|
||||
const elTag = unsafeStatic(elTagString);
|
||||
|
||||
class BundledValidator extends EventTarget {
|
||||
static ['_$isValidator$'] = true;
|
||||
|
||||
static validatorName = '';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.type = 'error';
|
||||
}
|
||||
|
||||
get config() {
|
||||
// simplified version of the actual config
|
||||
return {};
|
||||
}
|
||||
|
||||
execute() {
|
||||
// simplified version of the action execution
|
||||
return true;
|
||||
}
|
||||
|
||||
onFormControlConnect() {}
|
||||
|
||||
onFormControlDisconnect() {}
|
||||
|
||||
async _getMessage() {
|
||||
// simplified version of the actual logic
|
||||
return 'Success message.';
|
||||
}
|
||||
}
|
||||
|
||||
class BundledDefaultSuccess extends BundledValidator {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.type = 'success';
|
||||
}
|
||||
|
||||
executeOnResults() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const el = /** @type {ValidateElement} */ (
|
||||
await fixture(html`
|
||||
<${elTag}
|
||||
.validators=${[new Required(), new BundledDefaultSuccess()]}
|
||||
.modelValue=${'myValue'}
|
||||
>${lightDom}</${elTag}>
|
||||
`)
|
||||
);
|
||||
|
||||
expect(el.hasFeedbackFor).to.deep.equal(['success']);
|
||||
});
|
||||
|
||||
it('revalidates when ".modelValue" changes', async () => {
|
||||
const el = /** @type {ValidateElement} */ (
|
||||
await fixture(html`
|
||||
|
|
|
|||
Loading…
Reference in a new issue