diff --git a/packages/base/src/UI5Element.js b/packages/base/src/UI5Element.js index 4431a7af3d5e..165e9edbd827 100644 --- a/packages/base/src/UI5Element.js +++ b/packages/base/src/UI5Element.js @@ -59,10 +59,28 @@ class UI5Element extends HTMLElement { this._domRefReadyPromise._deferredResolve = deferredResolve; this._monitoredChildProps = new Map(); - this._firePropertyChange = false; + this._propertyChangeListeners = new Set(); this._shouldInvalidateParent = false; } + addEventListener(type, listener, options) { + if (type === "_property-change") { + this._propertyChangeListeners.add(listener); + } + return super.addEventListener(type, listener, options); + } + + removeEventListener(type, listener, options) { + if (type === "_property-change") { + this._propertyChangeListeners.delete(listener); + } + return super.removeEventListener(type, listener, options); + } + + _hasPropertyChangeListeners() { + return !!this._propertyChangeListeners.size; + } + /** * Returns a unique ID for this UI5 Element * @@ -394,9 +412,7 @@ class UI5Element extends HTMLElement { * @private */ _attachChildPropertyUpdated(child, listenFor) { - const childMetadata = child.constructor.getMetadata(), - slotName = this.constructor._getSlotName(child), // all slotted children have the same configuration - childProperties = childMetadata.getProperties(); + const slotName = this.constructor._getSlotName(child); // all slotted children have the same configuration let observedProps = [], notObservedProps = []; @@ -404,7 +420,7 @@ class UI5Element extends HTMLElement { if (Array.isArray(listenFor)) { observedProps = listenFor; } else { - observedProps = Array.isArray(listenFor.props) ? listenFor.props : Object.keys(childProperties); + observedProps = Array.isArray(listenFor.include) ? listenFor.include : []; notObservedProps = Array.isArray(listenFor.exclude) ? listenFor.exclude : []; } @@ -413,7 +429,6 @@ class UI5Element extends HTMLElement { } child.addEventListener("_property-change", this._invalidateParentOnPropertyUpdate); - child._firePropertyChange = true; } /** @@ -421,20 +436,19 @@ class UI5Element extends HTMLElement { */ _detachChildPropertyUpdated(child) { child.removeEventListener("_property-change", this._invalidateParentOnPropertyUpdate); - child._firePropertyChange = false; } /** - * @private + * @private */ _propertyChange(name, value) { this._updateAttribute(name, value); - if (this._firePropertyChange) { + if (this._hasPropertyChangeListeners()) { this.dispatchEvent(new CustomEvent("_property-change", { detail: { name, newValue: value }, composed: false, - bubbles: true, + bubbles: false, })); } } @@ -457,7 +471,10 @@ class UI5Element extends HTMLElement { } const { observedProps, notObservedProps } = propsMetadata; - if (observedProps.includes(prop.detail.name) && !notObservedProps.includes(prop.detail.name)) { + const allPropertiesAreObserved = observedProps.length === 1 && observedProps[0] === "*"; + const shouldObserve = allPropertiesAreObserved || observedProps.includes(prop.detail.name); + const shouldSkip = notObservedProps.includes(prop.detail.name); + if (shouldObserve && !shouldSkip) { parentNode._invalidate("_parent_", this); } }