fix: do not show ResultValidator feedback message if input field is empty
This commit is contained in:
parent
780d8a9691
commit
43dd132013
4 changed files with 59 additions and 6 deletions
5
.changeset/tender-otters-shake.md
Normal file
5
.changeset/tender-otters-shake.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/form-core': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: reset the form validators after a form `reset` click or field emptied
|
||||||
|
|
@ -23,7 +23,6 @@ To fire a submit from JavaScript, select the `lion-form` element and call `.subm
|
||||||
```js preview-story
|
```js preview-story
|
||||||
export const formSubmit = () => {
|
export const formSubmit = () => {
|
||||||
loadDefaultFeedbackMessages();
|
loadDefaultFeedbackMessages();
|
||||||
|
|
||||||
const submitHandler = ev => {
|
const submitHandler = ev => {
|
||||||
if (ev.target.hasFeedbackFor.includes('error')) {
|
if (ev.target.hasFeedbackFor.includes('error')) {
|
||||||
const firstFormElWithError = ev.target.formElements.find(el =>
|
const firstFormElWithError = ev.target.formElements.find(el =>
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,7 @@ export const ValidateMixinImplementation = superclass =>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* step b (as explained in `validate()`), called by __finishValidation
|
* step b (as explained in `validate()`), called by __finishValidation
|
||||||
* @param {{validator:Validator; outcome: boolean|string;}[]} regularValidationResult result of steps 1-3
|
* @param {{validator: Validator;outcome: boolean | string;}[]} regularValidationResult result of steps 1-3
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
__executeResultValidators(regularValidationResult) {
|
__executeResultValidators(regularValidationResult) {
|
||||||
|
|
@ -510,6 +510,16 @@ export const ValidateMixinImplementation = superclass =>
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!resultValidators.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If empty, do not show the ResulValidation message (e.g. Correct!)
|
||||||
|
if (this._isEmpty(this.modelValue)) {
|
||||||
|
this.__prevShownValidationResult = [];
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// Map everything to Validator[] for backwards compatibility
|
// Map everything to Validator[] for backwards compatibility
|
||||||
return resultValidators
|
return resultValidators
|
||||||
.map(v => ({
|
.map(v => ({
|
||||||
|
|
@ -537,8 +547,9 @@ export const ValidateMixinImplementation = superclass =>
|
||||||
__finishValidation({ source, hasAsync }) {
|
__finishValidation({ source, hasAsync }) {
|
||||||
const syncAndAsyncOutcome = [...this.__syncValidationResult, ...this.__asyncValidationResult];
|
const syncAndAsyncOutcome = [...this.__syncValidationResult, ...this.__asyncValidationResult];
|
||||||
// if we have any ResultValidators left, now is the time to run them...
|
// if we have any ResultValidators left, now is the time to run them...
|
||||||
const resultOutCome = this.__executeResultValidators(syncAndAsyncOutcome);
|
const resultOutCome = /** @type {ValidationResultEntry[]} */ (
|
||||||
|
this.__executeResultValidators(syncAndAsyncOutcome)
|
||||||
|
);
|
||||||
this.__validationResult = [...resultOutCome, ...syncAndAsyncOutcome];
|
this.__validationResult = [...resultOutCome, ...syncAndAsyncOutcome];
|
||||||
|
|
||||||
const ctor = /** @type {ValidateHostConstructor} */ (this.constructor);
|
const ctor = /** @type {ValidateHostConstructor} */ (this.constructor);
|
||||||
|
|
@ -560,7 +571,6 @@ export const ValidateMixinImplementation = superclass =>
|
||||||
this.hasFeedbackFor = [
|
this.hasFeedbackFor = [
|
||||||
...new Set(this.__validationResult.map(({ validator }) => validator.type)),
|
...new Set(this.__validationResult.map(({ validator }) => validator.type)),
|
||||||
];
|
];
|
||||||
|
|
||||||
/** private event that should be listened to by LionFieldSet */
|
/** private event that should be listened to by LionFieldSet */
|
||||||
this.dispatchEvent(new Event('validate-performed', { bubbles: true }));
|
this.dispatchEvent(new Event('validate-performed', { bubbles: true }));
|
||||||
if (source === 'async' || !hasAsync) {
|
if (source === 'async' || !hasAsync) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,14 @@ import { localizeTearDown } from '@lion/localize/test-helpers';
|
||||||
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
|
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
|
||||||
import { getFormControlMembers } from '@lion/form-core/test-helpers';
|
import { getFormControlMembers } from '@lion/form-core/test-helpers';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { DefaultSuccess, MinLength, Required, ValidateMixin, Validator } from '../index.js';
|
import {
|
||||||
|
DefaultSuccess,
|
||||||
|
MinLength,
|
||||||
|
MaxLength,
|
||||||
|
Required,
|
||||||
|
ValidateMixin,
|
||||||
|
Validator,
|
||||||
|
} from '../index.js';
|
||||||
import { AlwaysInvalid } from '../test-helpers/index.js';
|
import { AlwaysInvalid } from '../test-helpers/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -373,6 +380,38 @@ export function runValidateMixinFeedbackPart() {
|
||||||
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
expect(_feedbackNode.feedbackData?.[0].message).to.equal('This is a success message');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not show success message after fixing error an & field is empty', async () => {
|
||||||
|
class ValidateElementCustomTypes extends ValidateMixin(LitElement) {
|
||||||
|
static get validationTypes() {
|
||||||
|
return ['error', 'success'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const elTagString = defineCE(ValidateElementCustomTypes);
|
||||||
|
const elTag = unsafeStatic(elTagString);
|
||||||
|
const el = /** @type {ValidateElementCustomTypes} */ (
|
||||||
|
await fixture(html`
|
||||||
|
<${elTag}
|
||||||
|
.submitted=${true}
|
||||||
|
.validators=${[
|
||||||
|
new MaxLength(3, { getMessage: async () => 'Max length is 3!' }),
|
||||||
|
new DefaultSuccess(null, { getMessage: () => 'This is a success message' }),
|
||||||
|
]}
|
||||||
|
>${lightDom}</${elTag}>
|
||||||
|
`)
|
||||||
|
);
|
||||||
|
const { _feedbackNode } = getFormControlMembers(el);
|
||||||
|
|
||||||
|
el.modelValue = 'abcd';
|
||||||
|
await el.updateComplete;
|
||||||
|
await el.feedbackComplete;
|
||||||
|
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Max length is 3!');
|
||||||
|
|
||||||
|
el.modelValue = '';
|
||||||
|
await el.updateComplete;
|
||||||
|
await el.feedbackComplete;
|
||||||
|
expect(_feedbackNode.feedbackData).to.deep.equal([]);
|
||||||
|
});
|
||||||
|
|
||||||
describe('Accessibility', () => {
|
describe('Accessibility', () => {
|
||||||
it('sets [aria-invalid="true"] to "._inputNode" when there is an error', async () => {
|
it('sets [aria-invalid="true"] to "._inputNode" when there is an error', async () => {
|
||||||
const el = /** @type {ValidateElement} */ (
|
const el = /** @type {ValidateElement} */ (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue