Skip to content

Commit 3ca4ae1

Browse files
authored
fix(framework): component children that are slots now invalidate parent upon slotchange (#1649)
1 parent 65fbc12 commit 3ca4ae1

File tree

4 files changed

+35
-18
lines changed

4 files changed

+35
-18
lines changed

packages/base/src/UI5Element.js

+29-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import getEffectiveStyle from "./theming/getEffectiveStyle.js";
1212
import Integer from "./types/Integer.js";
1313
import { kebabToCamelCase, camelToKebabCase } from "./util/StringHelper.js";
1414
import isValidPropertyName from "./util/isValidPropertyName.js";
15+
import isSlot from "./util/isSlot.js";
1516

1617
const metadata = {
1718
events: {
@@ -237,6 +238,10 @@ class UI5Element extends HTMLElement {
237238
this._attachChildPropertyUpdated(child, slotData.listenFor);
238239
}
239240

241+
if (isSlot(child)) {
242+
this._attachSlotChange(child);
243+
}
244+
240245
const propertyName = slotData.propertyName || slotName;
241246

242247
if (slottedChildrenMap.has(propertyName)) {
@@ -272,6 +277,10 @@ class UI5Element extends HTMLElement {
272277
if (child && child.isUI5Element) {
273278
this._detachChildPropertyUpdated(child);
274279
}
280+
281+
if (isSlot(child)) {
282+
this._detachSlotChange(child);
283+
}
275284
});
276285

277286
this._state[propertyName] = [];
@@ -422,6 +431,25 @@ class UI5Element extends HTMLElement {
422431
}
423432
}
424433

434+
/**
435+
* @private
436+
*/
437+
_attachSlotChange(child) {
438+
if (!this._invalidateOnSlotChange) {
439+
this._invalidateOnSlotChange = () => {
440+
this._invalidate("slotchange");
441+
};
442+
}
443+
child.addEventListener("slotchange", this._invalidateOnSlotChange);
444+
}
445+
446+
/**
447+
* @private
448+
*/
449+
_detachSlotChange(child) {
450+
child.removeEventListener("slotchange", this._invalidateOnSlotChange);
451+
}
452+
425453
/**
426454
* Asynchronously re-renders an already rendered web component
427455
* @private
@@ -605,7 +633,7 @@ class UI5Element extends HTMLElement {
605633
*/
606634
getSlottedNodes(slotName) {
607635
const reducer = (acc, curr) => {
608-
if (curr.localName !== "slot") {
636+
if (!isSlot(curr)) {
609637
return acc.concat([curr]);
610638
}
611639
return acc.concat(curr.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement));

packages/base/src/UI5ElementMetadata.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import DataType from "./types/DataType.js";
22
import isDescendantOf from "./util/isDescendantOf.js";
33
import { camelToKebabCase } from "./util/StringHelper.js";
4+
import isSlot from "./util/isSlot.js";
45

56
/**
67
*
@@ -150,10 +151,7 @@ const validateSingleSlot = (value, slotData) => {
150151
}
151152

152153
const getSlottedNodes = el => {
153-
const isTag = el instanceof HTMLElement;
154-
const isSlot = isTag && el.localName === "slot";
155-
156-
if (isSlot) {
154+
if (isSlot(el)) {
157155
return el.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement);
158156
}
159157

packages/base/src/util/isSlot.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const isSlot = el => el && el instanceof HTMLElement && el.localName === "slot";
2+
3+
export default isSlot;

packages/main/src/Input.js

+1-13
Original file line numberDiff line numberDiff line change
@@ -863,19 +863,7 @@ class Input extends UI5Element {
863863
}
864864

865865
get valueStateMessageText() {
866-
const valueStateMessage = [];
867-
868-
this.valueStateMessage.forEach(el => {
869-
if (el.localName === "slot") {
870-
el.assignedNodes({ flatten: true }).forEach(assignedNode => {
871-
valueStateMessage.push(assignedNode.cloneNode(true));
872-
});
873-
} else {
874-
valueStateMessage.push(el.cloneNode(true));
875-
}
876-
});
877-
878-
return valueStateMessage;
866+
return this.getSlottedNodes("valueStateMessage").map(el => el.cloneNode(true));
879867
}
880868

881869
get shouldDisplayOnlyValueStateMessage() {

0 commit comments

Comments
 (0)