Skip to content

Commit 2511bf6

Browse files
committed
fix(field): the FormatMixin should work without an inputElement
1 parent 3981985 commit 2511bf6

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

packages/field/src/FormatMixin.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ export const FormatMixin = dedupeMixin(
230230
// imperatively, we DO want to format a value (it is the only way to get meaningful
231231
// input into `.inputElement` with modelValue as input)
232232

233-
if (this.__isHandlingUserInput && this.errorState) {
233+
if (this.__isHandlingUserInput && this.errorState && this.inputElement) {
234234
return this.inputElement ? this.value : undefined;
235235
}
236236
return this.formatter(this.modelValue, this.formatOptions);
@@ -335,8 +335,6 @@ export const FormatMixin = dedupeMixin(
335335
// is guaranteed to be calculated
336336
setTimeout(this._reflectBackFormattedValueToUser);
337337
};
338-
this.inputElement.addEventListener(this.formatOn, this._reflectBackFormattedValueDebounced);
339-
this.inputElement.addEventListener('input', this._proxyInputEvent);
340338
this.addEventListener('user-input-changed', this._onUserInputChanged);
341339
// Connect the value found in <input> to the formatting/parsing/serializing loop as a
342340
// fallback mechanism. Assume the user uses the value property of the
@@ -347,16 +345,26 @@ export const FormatMixin = dedupeMixin(
347345
this._syncValueUpwards();
348346
}
349347
this._reflectBackFormattedValueToUser();
348+
349+
if (this.inputElement) {
350+
this.inputElement.addEventListener(
351+
this.formatOn,
352+
this._reflectBackFormattedValueDebounced,
353+
);
354+
this.inputElement.addEventListener('input', this._proxyInputEvent);
355+
}
350356
}
351357

352358
disconnectedCallback() {
353359
super.disconnectedCallback();
354-
this.inputElement.removeEventListener('input', this._proxyInputEvent);
355360
this.removeEventListener('user-input-changed', this._onUserInputChanged);
356-
this.inputElement.removeEventListener(
357-
this.formatOn,
358-
this._reflectBackFormattedValueDebounced,
359-
);
361+
if (this.inputElement) {
362+
this.inputElement.removeEventListener('input', this._proxyInputEvent);
363+
this.inputElement.removeEventListener(
364+
this.formatOn,
365+
this._reflectBackFormattedValueDebounced,
366+
);
367+
}
360368
}
361369
},
362370
);

packages/field/test/FormatMixin.test.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect, fixture, html, aTimeout, defineCE, unsafeStatic } from '@open-wc/testing';
22
import sinon from 'sinon';
33

4-
import { LionLitElement } from '@lion/core/src/LionLitElement.js';
4+
import { LitElement } from '@lion/core';
55
import { Unparseable } from '@lion/validate';
66
import { FormatMixin } from '../src/FormatMixin.js';
77

@@ -17,7 +17,7 @@ describe('FormatMixin', () => {
1717

1818
before(async () => {
1919
const tagString = defineCE(
20-
class extends FormatMixin(LionLitElement) {
20+
class extends FormatMixin(LitElement) {
2121
render() {
2222
return html`
2323
<slot name="input"></slot>
@@ -176,6 +176,14 @@ describe('FormatMixin', () => {
176176
expect(el.inputElement.value).to.equal('foo: test2');
177177
});
178178

179+
it('works if there is no underlying inputElement', async () => {
180+
const tagNoInputString = defineCE(class extends FormatMixin(LitElement) {});
181+
const tagNoInput = unsafeStatic(tagNoInputString);
182+
expect(async () => {
183+
await fixture(html`<${tagNoInput}></${tagNoInput}>`);
184+
}).to.not.throw();
185+
});
186+
179187
describe('parsers/formatters/serializers', () => {
180188
it('should call the parser|formatter|serializer provided by user', async () => {
181189
const formatterSpy = sinon.spy(value => `foo: ${value}`);

0 commit comments

Comments
 (0)