Skip to content

Commit a1a3f80

Browse files
authored
feat(framework): Change child-parent invalidation API (#2541)
1 parent 10a6b92 commit a1a3f80

34 files changed

+594
-336
lines changed

docs/dev/Metadata.md

+96-7
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,101 @@ Defines the `slots` that will be provided by this UI5 Web Component.
109109

110110
Setting | Type | Default | Description
111111
--------|------|--------|-----------
112-
`type` | `HTMLElement` or `Node` | N/A | The type of the children that can go into that slot
112+
`type` * | `HTMLElement` or `Node` | N/A | The type of the children that can go into that slot
113113
`individualSlots` | `Boolean` | false | If set to `true`, each child will have its own slot, allowing you to arrange/wrap the children arbitrarily.
114-
`propertyName` | `String` | N/A | Allows to set the name of the property on the Web Component, where the children belonging to this slot will be stored.
115-
`listenFor` | `Object` | N/A | **Experimental, do not use.** If set, whenever the children, belonging to this slot have their properties changed, the Web Component will be invalidated.
116-
`invalidateParent` | `Boolean` | false | **Experimental, do not use.** Defines whether every invalidation of a UI5 Web Component in this slot should trigger an invalidation of the parent UI5 Web Component.
117-
The `type` setting is required.
114+
`propertyName` | `String` | N/A | Allows to set the name of the property on the Web Component, where the children belonging to this slot will be stored.
115+
`invalidateOnChildChange` ** | `Boolean` or `Object` | false | **Experimental, do not use.** Defines whether every invalidation of a UI5 Web Component in this slot should trigger an invalidation of the parent UI5 Web Component.
116+
117+
`*` The `type` setting is required.
118+
119+
`**`
120+
**Important:** `invalidateOnChildChange` is not meant to be used with standard DOM Elements and is not to be confused with `MutationObserver`-like functionality.
121+
It rather targets the use case of components that slot abstract items (`UI5Element` instances without a template) and require to be invalidated in turn whenever these items are invalidated.
122+
123+
The `invalidateOnChildChange` setting can be either a `Boolean` (`true` meaning invalidate the component on any change of a child in this slot) or an `Object` with `properties` and `slots` fields. They in turn can be either of
124+
type `Boolean` (`true` meaning invalidate on any property change or any slot change) or `Array` of strings indicating exactly which properties or slots lead to invalidation.
125+
126+
Examples:
127+
128+
- In the following example, since `invalidateOnChildChange` is not used (`false` by default), the component will be invalidated whenever children are added/removed in the `tabs` slot,
129+
but not whenever a child in that slot changes.
130+
```json
131+
{
132+
managedSlots: true,
133+
slots: {
134+
"default": {
135+
"type": "HTMLElement",
136+
"propertyName": "tabs",
137+
}
138+
}
139+
}
140+
```
141+
142+
- Setting `invalidateOnChildChange` to `true` means: invalidate the component whenever a child in the `tabs` slot gets invalidated, regardless of the reason.
143+
```json
144+
{
145+
managedSlots: true,
146+
slots: {
147+
"default": {
148+
"type": "HTMLElement",
149+
"propertyName": "tabs",
150+
"invalidateOnChildChange": true
151+
}
152+
}
153+
}
154+
```
155+
156+
- The example below results in exactly the same behavior as the one above, but it uses the more explicit `Object` format:
157+
```json
158+
{
159+
managedSlots: true,
160+
slots: {
161+
"default": {
162+
"type": "HTMLElement",
163+
"propertyName": "tabs",
164+
"invalidateOnChildChange": {
165+
"properties": true,
166+
"slots": true
167+
}
168+
}
169+
}
170+
}
171+
```
172+
173+
- The following example uses the `Object` format again and means: invalidate the component whenever the children in this slot are invalidated due to property changes, but not due
174+
to slot changes. Here `"slots": false` is added for completeness (as `false` is the default value for both `properties` and `slots`)
175+
```json
176+
{
177+
managedSlots: true,
178+
slots: {
179+
"default": {
180+
"type": "HTMLElement",
181+
"propertyName": "tabs",
182+
"invalidateOnChildChange": {
183+
"properties": true,
184+
"slots": false
185+
}
186+
}
187+
}
188+
}
189+
```
190+
191+
- The final example shows the most complex format of `invalidateOnChildChange` which allows to define which slots or properties in the children inside that slot lead to invalidation of the component:
192+
```json
193+
{
194+
managedSlots: true,
195+
slots: {
196+
"default": {
197+
"type": "HTMLElement",
198+
"propertyName": "tabs",
199+
"invalidateOnChildChange": {
200+
"properties": ["text", "selected", "disabled"],
201+
"slots": ["default"]
202+
}
203+
}
204+
}
205+
}
206+
```
118207

119208
Notes:
120209
- Children without a `slot` attribute will be assigned to the `default` slot.
@@ -135,7 +224,7 @@ Notes:
135224

136225
Determines whether the framework should manage the slots of this UI5 Web Component.
137226

138-
This setting is useful for UI5 Web Components that dont' just slot children, but additionally base their own
227+
This setting is useful for UI5 Web Components that don't just slot children, but additionally base their own
139228
rendering on the presence/absence/type of children.
140229

141230
```json
@@ -145,7 +234,7 @@ rendering on the presence/absence/type of children.
145234
```
146235

147236
When `managedSlots` is set to `true`:
148-
- The framework will invalidate this UI5 Web Component, whenever its children are added/removed/changed.
237+
- The framework will invalidate this UI5 Web Component, whenever its children are added/removed/rearranged (and additionally when invalidated, if `invalidateOnChildChange` is set).
149238
- If any of this UI5 Web Component's children are custom elements, the framework will await until they are all
150239
defined and upgraded, before rendering the component for the first time.
151240
- The framework will create properties for each slot on this UI5 Web Component's instances for easier access

packages/base/src/RenderScheduler.js

+3
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ class RenderScheduler {
6363
queuePromise = new Promise(resolve => {
6464
window.requestAnimationFrame(() => {
6565
// Render all components in the queue
66+
67+
// console.log(`--------------------RENDER TASK START------------------------------`); // eslint-disable-line
6668
invalidatedWebComponents.process(component => component._render());
69+
// console.log(`--------------------RENDER TASK END------------------------------`); // eslint-disable-line
6770

6871
// Resolve the promise so that callers of renderDeferred can continue
6972
queuePromise = null;

0 commit comments

Comments
 (0)