diff --git a/packages/field/src/FormatMixin.js b/packages/field/src/FormatMixin.js
index a9d813204..a63fcef44 100644
--- a/packages/field/src/FormatMixin.js
+++ b/packages/field/src/FormatMixin.js
@@ -230,7 +230,7 @@ export const FormatMixin = dedupeMixin(
// imperatively, we DO want to format a value (it is the only way to get meaningful
// input into `.inputElement` with modelValue as input)
- if (this.__isHandlingUserInput && this.errorState) {
+ if (this.__isHandlingUserInput && this.errorState && this.inputElement) {
return this.inputElement ? this.value : undefined;
}
return this.formatter(this.modelValue, this.formatOptions);
@@ -335,8 +335,6 @@ export const FormatMixin = dedupeMixin(
// is guaranteed to be calculated
setTimeout(this._reflectBackFormattedValueToUser);
};
- this.inputElement.addEventListener(this.formatOn, this._reflectBackFormattedValueDebounced);
- this.inputElement.addEventListener('input', this._proxyInputEvent);
this.addEventListener('user-input-changed', this._onUserInputChanged);
// Connect the value found in to the formatting/parsing/serializing loop as a
// fallback mechanism. Assume the user uses the value property of the
@@ -347,16 +345,26 @@ export const FormatMixin = dedupeMixin(
this._syncValueUpwards();
}
this._reflectBackFormattedValueToUser();
+
+ if (this.inputElement) {
+ this.inputElement.addEventListener(
+ this.formatOn,
+ this._reflectBackFormattedValueDebounced,
+ );
+ this.inputElement.addEventListener('input', this._proxyInputEvent);
+ }
}
disconnectedCallback() {
super.disconnectedCallback();
- this.inputElement.removeEventListener('input', this._proxyInputEvent);
this.removeEventListener('user-input-changed', this._onUserInputChanged);
- this.inputElement.removeEventListener(
- this.formatOn,
- this._reflectBackFormattedValueDebounced,
- );
+ if (this.inputElement) {
+ this.inputElement.removeEventListener('input', this._proxyInputEvent);
+ this.inputElement.removeEventListener(
+ this.formatOn,
+ this._reflectBackFormattedValueDebounced,
+ );
+ }
}
},
);
diff --git a/packages/field/test/FormatMixin.test.js b/packages/field/test/FormatMixin.test.js
index 1c7905364..aa004ca70 100644
--- a/packages/field/test/FormatMixin.test.js
+++ b/packages/field/test/FormatMixin.test.js
@@ -1,7 +1,7 @@
import { expect, fixture, html, aTimeout, defineCE, unsafeStatic } from '@open-wc/testing';
import sinon from 'sinon';
-import { LionLitElement } from '@lion/core/src/LionLitElement.js';
+import { LitElement } from '@lion/core';
import { Unparseable } from '@lion/validate';
import { FormatMixin } from '../src/FormatMixin.js';
@@ -17,7 +17,7 @@ describe('FormatMixin', () => {
before(async () => {
const tagString = defineCE(
- class extends FormatMixin(LionLitElement) {
+ class extends FormatMixin(LitElement) {
render() {
return html`
@@ -176,6 +176,14 @@ describe('FormatMixin', () => {
expect(el.inputElement.value).to.equal('foo: test2');
});
+ it('works if there is no underlying inputElement', async () => {
+ const tagNoInputString = defineCE(class extends FormatMixin(LitElement) {});
+ const tagNoInput = unsafeStatic(tagNoInputString);
+ expect(async () => {
+ await fixture(html`<${tagNoInput}>${tagNoInput}>`);
+ }).to.not.throw();
+ });
+
describe('parsers/formatters/serializers', () => {
it('should call the parser|formatter|serializer provided by user', async () => {
const formatterSpy = sinon.spy(value => `foo: ${value}`);