fix: do not show ResultValidator feedback message if input field is empty

This commit is contained in:
Konstantinos Norgias 2022-04-19 10:27:38 +02:00
parent 780d8a9691
commit 43dd132013
4 changed files with 59 additions and 6 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/form-core': patch
---
fix: reset the form validators after a form `reset` click or field emptied

View file

@ -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 =>

View file

@ -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) {

View file

@ -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} */ (