diff --git a/packages/component-base/src/polylit-mixin.js b/packages/component-base/src/polylit-mixin.js index fdb64933bb..1405f3b333 100644 --- a/packages/component-base/src/polylit-mixin.js +++ b/packages/component-base/src/polylit-mixin.js @@ -4,6 +4,7 @@ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ */ import { dedupeMixin } from '@open-wc/dedupe-mixin'; +import { notEqual } from 'lit'; import { get, set } from './path-utils.js'; const caseMap = {}; @@ -101,12 +102,15 @@ const PolylitMixinImplementation = (superclass) => { get: defaultDescriptor.get, set(value) { const oldValue = this[name]; - this[key] = value; - this.requestUpdate(name, oldValue, options); - // Enforce synchronous update - if (this.hasUpdated) { - this.performUpdate(); + if (notEqual(value, oldValue)) { + this[key] = value; + this.requestUpdate(name, oldValue, options); + + // Enforce synchronous update + if (this.hasUpdated) { + this.performUpdate(); + } } }, configurable: true, @@ -115,21 +119,17 @@ const PolylitMixinImplementation = (superclass) => { } if (options.readOnly) { - const setter = defaultDescriptor.set; + const setter = result.set; this.addCheckedInitializer((instance) => { // This is run during construction of the element instance[`_set${upper(name)}`] = function (value) { setter.call(instance, value); - - if (options.sync) { - this.performUpdate(); - } }; }); result = { - get: defaultDescriptor.get, + get: result.get, set() { // Do nothing, property is read-only. }, diff --git a/packages/component-base/src/resize-mixin.js b/packages/component-base/src/resize-mixin.js index 65dde68c03..d5690d5fe7 100644 --- a/packages/component-base/src/resize-mixin.js +++ b/packages/component-base/src/resize-mixin.js @@ -8,6 +8,10 @@ import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js'; const observer = new ResizeObserver((entries) => { setTimeout(() => { entries.forEach((entry) => { + if (!entry.target.isConnected) { + return; + } + // Notify child resizables, if any if (entry.target.resizables) { entry.target.resizables.forEach((resizable) => { diff --git a/packages/component-base/test/polylit-mixin.test.js b/packages/component-base/test/polylit-mixin.test.js index bb3be2562d..e2e40f60bf 100644 --- a/packages/component-base/test/polylit-mixin.test.js +++ b/packages/component-base/test/polylit-mixin.test.js @@ -1051,6 +1051,20 @@ describe('PolylitMixin', () => { expect(element.hasAttribute('helper')).to.be.true; }); + it('should not reflect immediately when setting a read-only sync property to the same value', () => { + element._setOpened(true); + element._setHelper('foo'); // async property + element._setOpened(true); // sync property + expect(element.hasAttribute('helper')).to.be.false; + }); + + it('should not reflect immediately when setting sync property to the same value', () => { + element.disabled = true; + element._setHelper('foo'); // async property + element.disabled = true; // sync property + expect(element.hasAttribute('helper')).to.be.false; + }); + it('should only call ready callback once during initialization', () => { expect(element.count).to.equal(1); }); diff --git a/packages/date-picker/src/vaadin-date-picker-mixin.js b/packages/date-picker/src/vaadin-date-picker-mixin.js index a86333364f..4ecde25230 100644 --- a/packages/date-picker/src/vaadin-date-picker-mixin.js +++ b/packages/date-picker/src/vaadin-date-picker-mixin.js @@ -1211,10 +1211,7 @@ export const DatePickerMixin = (subclass) => if (!dateEquals(this.__enteredDate, date)) { this.__enteredDate = date; } - } else if (this.__enteredDate != null) { - // Do not override initial undefined value with null - // to avoid triggering a Lit update that can cause - // other scheduled properties to flush too early. + } else { this.__enteredDate = null; } } diff --git a/packages/field-base/src/input-mixin.js b/packages/field-base/src/input-mixin.js index cca36069e7..edf65b81fb 100644 --- a/packages/field-base/src/input-mixin.js +++ b/packages/field-base/src/input-mixin.js @@ -63,6 +63,7 @@ export const InputMixin = dedupingMixin( type: Boolean, value: false, observer: '_hasInputValueChanged', + sync: true, }, }; } diff --git a/packages/grid/src/vaadin-grid-column-group-mixin.js b/packages/grid/src/vaadin-grid-column-group-mixin.js index ad957e855e..afacd6bc5e 100644 --- a/packages/grid/src/vaadin-grid-column-group-mixin.js +++ b/packages/grid/src/vaadin-grid-column-group-mixin.js @@ -41,6 +41,7 @@ export const GridColumnGroupMixin = (superClass) => width: { type: String, readOnly: true, + sync: true, }, /** @private */ diff --git a/packages/grid/src/vaadin-grid-column-mixin.js b/packages/grid/src/vaadin-grid-column-mixin.js index 62200a1393..247096d5fc 100644 --- a/packages/grid/src/vaadin-grid-column-mixin.js +++ b/packages/grid/src/vaadin-grid-column-mixin.js @@ -177,10 +177,16 @@ export const ColumnBaseMixin = (superClass) => _emptyCells: Array, /** @private */ - _headerCell: Object, + _headerCell: { + type: Object, + sync: true, + }, /** @private */ - _footerCell: Object, + _footerCell: { + type: Object, + sync: true, + }, /** @protected */ _grid: Object, diff --git a/packages/grid/src/vaadin-grid-sorter-mixin.js b/packages/grid/src/vaadin-grid-sorter-mixin.js index 0c81398bd4..76187a68a2 100644 --- a/packages/grid/src/vaadin-grid-sorter-mixin.js +++ b/packages/grid/src/vaadin-grid-sorter-mixin.js @@ -117,6 +117,14 @@ export const GridSorterMixin = (superClass) => /** @protected */ connectedCallback() { super.connectedCallback(); + + if (this.performUpdate) { + // Force Lit's first render to be synchronous to ensure + // _pathOrDirectionChanged is triggered before grid's + // __applySorters, as it is in Polymer. + this.performUpdate(); + } + if (this._grid) { this._grid.__applySorters(); } else { diff --git a/packages/item/src/vaadin-item-mixin.js b/packages/item/src/vaadin-item-mixin.js index f43080d0ee..75d2fdf144 100644 --- a/packages/item/src/vaadin-item-mixin.js +++ b/packages/item/src/vaadin-item-mixin.js @@ -38,6 +38,7 @@ export const ItemMixin = (superClass) => value: false, reflectToAttribute: true, observer: '_selectedChanged', + sync: true, }, /** @private */ diff --git a/packages/select/src/vaadin-select-base-mixin.js b/packages/select/src/vaadin-select-base-mixin.js index f655296a47..cc160fe5f7 100644 --- a/packages/select/src/vaadin-select-base-mixin.js +++ b/packages/select/src/vaadin-select-base-mixin.js @@ -97,6 +97,7 @@ export const SelectBaseMixin = (superClass) => value: '', notify: true, observer: '_valueChanged', + sync: true, }, /**