diff --git a/packages/fieldset/src/LionFieldset.js b/packages/fieldset/src/LionFieldset.js index e0d25d468..6e04af64b 100644 --- a/packages/fieldset/src/LionFieldset.js +++ b/packages/fieldset/src/LionFieldset.js @@ -101,38 +101,25 @@ export class LionFieldset extends FormRegistrarMixin( this.__createTypeAbsenceValidators(); this._checkForOutsideClick = this._checkForOutsideClick.bind(this); + + this.addEventListener('focusin', this._syncFocused); + this.addEventListener('focusout', this._onFocusOut); + this.addEventListener('validation-done', this.__validate); + this.addEventListener('dirty-changed', this._syncDirty); } connectedCallback() { - // eslint-disable-next-line wc/guard-super-call - super.connectedCallback(); - - this.addEventListener('focusin', this._updateTouchedClass); - this.addEventListener('focusout', this._onFocusOut); - this.addEventListener('focusin', this._syncFocused); - - this.addEventListener('validation-done', this.__validate); - this.addEventListener('dirty-changed', this._syncDirty); - + super.connectedCallback(); // eslint-disable-line wc/guard-super-call this._setRole(); - document.addEventListener('click', this._checkForOutsideClick); - } - - _checkForOutsideClick(event) { - const outsideGroupClicked = !this.contains(event.target); - if (outsideGroupClicked) { - this.touched = true; - } } disconnectedCallback() { - // eslint-disable-next-line wc/guard-super-call - super.disconnectedCallback(); - this.removeEventListener('validation-done', this.__validate); - this.removeEventListener('touched-changed', this._updateTouched); - this.removeEventListener('dirty-changed', this._syncDirty); + super.disconnectedCallback(); // eslint-disable-line wc/guard-super-call - document.removeEventListener('click', this._checkForOutsideClick); + if (this.__hasActiveOutsideClickHandling) { + document.removeEventListener('click', this._checkForOutsideClick); + this.__hasActiveOutsideClickHandling = false; + } } updated(changedProps) { @@ -162,6 +149,23 @@ export class LionFieldset extends FormRegistrarMixin( if (changedProps.has('focused')) { /** @deprecated use touched attribute instead */ this.classList[this.focused ? 'add' : 'remove']('state-focused'); + if (this.focused === true) { + this.__setupOutsideClickHandling(); + } + } + } + + __setupOutsideClickHandling() { + if (!this.__hasActiveOutsideClickHandling) { + document.addEventListener('click', this._checkForOutsideClick); + this.__hasActiveOutsideClickHandling = true; + } + } + + _checkForOutsideClick(event) { + const outsideGroupClicked = !this.contains(event.target); + if (outsideGroupClicked) { + this.touched = true; } } diff --git a/packages/fieldset/stories/index.stories.js b/packages/fieldset/stories/index.stories.js index a20479c5e..7c59afc00 100644 --- a/packages/fieldset/stories/index.stories.js +++ b/packages/fieldset/stories/index.stories.js @@ -84,52 +84,20 @@ storiesOf('Forms|Fieldset', module) `, ) - .add('Validation 2 inputs', () => { - const input1IsTen = value => ({ - input1IsTen: value.input1 === 'cats' && value.input2 === 'dogs', - }); - localize.locale = 'en-GB'; - try { - localize.addData('en-GB', 'lion-validate+input1IsTen', { - error: { - input1IsTen: 'Input 1 needs to be "cats" and Input 2 needs to be "dogs"', - }, - }); - } catch (error) { - // expected as it's a demo - } - - return html` - - - - - `; - }) .add('Validation', () => { - function isFakeValidator() { + function isDemoValidator() { return false; } - const fakeValidator = (...factoryParams) => [ - (...params) => ({ validator: isFakeValidator(...params) }), + const demoValidator = (...factoryParams) => [ + (...params) => ({ validator: isDemoValidator(...params) }), ...factoryParams, ]; try { localize.addData('en-GB', 'lion-validate+validator', { error: { - validator: 'Fake error message', + validator: 'Demo error message', }, }); } catch (error) { @@ -137,7 +105,7 @@ storiesOf('Forms|Fieldset', module) } return html` - + `; + }) + .add('Validation 2 inputs', () => { + const isCatsAndDogs = value => ({ + isCatsAndDogs: value.input1 === 'cats' && value.input2 === 'dogs', + }); + localize.locale = 'en-GB'; + try { + localize.addData('en-GB', 'lion-validate+isCatsAndDogs', { + error: { + isCatsAndDogs: + '[Fieldset Error] Input 1 needs to be "cats" and Input 2 needs to be "dogs"', + }, + }); + } catch (error) { + // expected as it's a demo + } + + return html` + + + + + `; + }) + .add('Validation 2 fieldsets', () => { + const isCats = value => ({ + isCats: value.input1 === 'cats', + }); + localize.locale = 'en-GB'; + try { + localize.addData('en-GB', 'lion-validate+isCats', { + error: { + isCats: '[Fieldset Nr. 1 Error] Input 1 needs to be "cats"', + }, + }); + } catch (error) { + // expected as it's a demo + } + + const isDogs = value => ({ + isDogs: value.input1 === 'dogs', + }); + localize.locale = 'en-GB'; + try { + localize.addData('en-GB', 'lion-validate+isDogs', { + error: { + isDogs: '[Fieldset Nr. 2 Error] Input 1 needs to be "dogs"', + }, + }); + } catch (error) { + // expected as it's a demo + } + + return html` + + + + +
+
+
+ + + + + `; }); diff --git a/packages/fieldset/test/lion-fieldset.test.js b/packages/fieldset/test/lion-fieldset.test.js index 7ba6fdff5..d07ca0aae 100644 --- a/packages/fieldset/test/lion-fieldset.test.js +++ b/packages/fieldset/test/lion-fieldset.test.js @@ -421,17 +421,30 @@ describe('', () => { <${childTag} name="input2"> `); + const el2 = await fixture(html` + <${tag}> + <${childTag} name="input1"> + <${childTag} name="input2"> + + `); + await nextFrame(); const outside = await fixture(html` `); + outside.click(); + expect(el.touched, 'unfocused fieldset should stays untouched').to.be.false; + el.children[1].focus(); el.children[2].focus(); expect(el.touched).to.be.false; outside.click(); // blur the group via a click + outside.focus(); // a real mouse click moves focus as well expect(el.touched).to.be.true; + + expect(el2.touched).to.be.false; }); it('potentially shows fieldset error message on interaction change', async () => {