diff --git a/lib/mixins/properties-changed.html b/lib/mixins/properties-changed.html index aca31674af..ac5481b131 100644 --- a/lib/mixins/properties-changed.html +++ b/lib/mixins/properties-changed.html @@ -143,7 +143,7 @@ /* eslint-disable valid-jsdoc */ /** @this {PropertiesChanged} */ get() { - return this.__data[property]; + return this._getProperty(property); }, /** @this {PropertiesChanged} */ set: readOnly ? function () {} : function (value) { @@ -332,13 +332,31 @@ * @protected */ _flushProperties() { - if (this.__dataPending && this.__dataOld) { - let changedProps = this.__dataPending; + const props = this.__data; + const changedProps = this.__dataPending; + const old = this.__dataOld; + if (this._shouldPropertiesChange(props, changedProps, old)) { this.__dataPending = null; - this._propertiesChanged(this.__data, changedProps, this.__dataOld); + this._propertiesChanged(props, changedProps, old); } } + /** + * Called in `_flushProperties` to determine if `_propertiesChanged` + * should be called. The default implementation returns true if + * properties are pending. Override to customize when + * `_propertiesChanged` is called. + * @param {!Object} currentProps Bag of all current accessor values + * @param {!Object} changedProps Bag of properties changed since the last + * call to `_propertiesChanged` + * @param {!Object} oldProps Bag of previous values for each property + * in `changedProps` + * @return {boolean} true if changedProps is truthy + */ + _shouldPropertiesChange(props, changedProps, old) { + return changedProps; + } + /** * Callback called when any properties with accessors created via * `_createPropertyAccessor` have been set. diff --git a/test/unit/properties-changed.html b/test/unit/properties-changed.html index dc835d7ad8..eebb662706 100644 --- a/test/unit/properties-changed.html +++ b/test/unit/properties-changed.html @@ -56,6 +56,24 @@ } window.XFoo = XFoo; customElements.define('x-foo', XFoo); + + class ShouldPropertiesChange extends Polymer.PropertiesChanged(HTMLElement) { + constructor() { + super(); + this._propertiesChanged = sinon.spy(); + } + + connectedCallback() { + this._enableProperties(); + //this._flushProperties(); + } + + _shouldPropertiesChange() { + return true; + } + } + + customElements.define('should-properties-change', ShouldPropertiesChange); }); @@ -129,6 +147,21 @@ }); }); + test('shouldPropertiesChange', function(done) { + const el = document.createElement('should-properties-change'); + document.body.appendChild(el); + assert.isTrue(el._propertiesChanged.calledOnce); + el._invalidateProperties(); + setTimeout(function() { + assert.isTrue(el._propertiesChanged.calledTwice); + el._setProperty('foo', true); + setTimeout(function() { + assert.isTrue(el._propertiesChanged.calledThrice); + done(); + }); + }); + }) + });