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();
+ });
+ });
+ })
+
});