You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs-src/pages/data-flow.md
+20-14Lines changed: 20 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,7 @@ Let's consider a **product catalog** where users can add items to a shopping car
21
21
- **Tracks all `SpinButton` components** in its subtree and calculates the total count of items in the shopping cart.
22
22
- **Passes that total** to a `InputButton`.
23
23
*`InputButton`**(Child)**:
24
-
- Displays a **badge** in the top-right corner when the `'badge'` signal is set.
24
+
- Displays a **badge** in the top-right corner when the `badge` property is set.
25
25
- **Does not track any state** – it simply renders whatever value is passed to it.
26
26
*`SpinButton`**(Child)**:
27
27
- Displays an **Add to Cart** button initially.
@@ -32,28 +32,34 @@ So `ProductCatalog` **coordinates the data flow between them**.
32
32
33
33
### Parent Component: ProductCatalog
34
34
35
-
The **parent component (`ProductCatalog`) knows about its children**, meaning it can **observe and pass state** to them.
35
+
The **parent component (`ProductCatalog`) knows about its children**, meaning it can **retrieve state from and pass state to** them.
36
36
37
37
First, we need to observe the quantities of all `SpinButton` components. For this, we create a signal of all children matching the `spin-button` selector:
38
38
39
39
```js
40
40
component("product-catalog", {
41
-
quantities: (el) =>selection(el, "spin-button"),
41
+
total: (el) => () =>
42
+
selection(el, "spin-button")
43
+
.get()
44
+
.reduce((sum, item) => sum +item.value, 0),
42
45
}, () => []);
43
46
```
44
47
45
48
The `selection()` function returns a signal that emits an array of all matching elements. In contrast to a static `querySelectorAll()` call, the `selection()` function is reactive and updates whenever new elements are added or removed from the DOM.
46
49
47
-
Then, we need to calculate the total of all product quantities and pass it on to the `InputButton` component. As states in UIElement are accessed through normal properties we use the `setProperty()`effect to send values to child components:
50
+
Then, we need to calculate the total of all product quantities and pass it on to the `InputButton` component. In UIElement we use the `pass()`function to share state across components:
48
51
49
52
```js
50
53
component("product-catalog", {
51
-
quantities: (el) =>selection(el, "spin-button"),
54
+
total: (el) => () =>
55
+
selection(el, "spin-button")
56
+
.get()
57
+
.reduce((sum, item) => sum +item.value, 0),
52
58
}, (el) => [
53
59
first("input-button",
54
-
setProperty("badge", () =>{
55
-
consttotal=el.quantities.reduce((sum, item) => sum +item.value, 0);
56
-
return total >0?String(total) :"";
60
+
pass({
61
+
badge: () => (el.total>0?String(el.total) :""),
62
+
disabled: () =>!el.total,
57
63
}),
58
64
),
59
65
]);
@@ -77,7 +83,7 @@ component("input-button", {
77
83
```
78
84
79
85
* ✅ Whenever the `badge` property is updated by a parent component, the badge text updates.
80
-
* ✅ If badge is an empty string, the badge is hidden (via CSS).
86
+
* ✅ If `badge` is an empty string, the badge indicator is hidden (via CSS).
81
87
82
88
### ChildComponent: SpinButton
83
89
@@ -139,8 +145,8 @@ Here's how everything comes together:
139
145
<product-catalog>
140
146
<header>
141
147
<p>Shop</p>
142
-
<input-button>
143
-
<button type="button">
148
+
<input-button disabled>
149
+
<button type="button" disabled>
144
150
<span class="label">🛒 Shopping Cart</span>
145
151
<span class="badge"></span>
146
152
</button>
@@ -209,16 +215,16 @@ Let's consider a Todo App, where users can add tasks:
209
215
210
216
*`TodoApp`**(Parent)**:
211
217
- Holds the list of todos as a state signal.
212
-
- Listens for an `'add-todo'` event from the child (`TodoForm`).
218
+
- Listens for an `add-todo` event from the child (`TodoForm`).
213
219
- Updates the state when a new todo is submitted.
214
220
*`TodoForm`**(Child)**:
215
221
- Handles **user input** but does **not** store todos.
216
-
- Emits an `'add-todo'` event when the user submits the form.
222
+
- Emits an `add-todo` event when the user submits the form.
217
223
- Lets the parent decide **what to do with the data**.
218
224
219
225
### Why use events here?
220
226
221
-
* The child **doesn’t need to know where the data goes** – it just **emits an event**.
227
+
* The child **doesn't need to know where the data goes** – it just **emits an event**.
222
228
* The parent **decides what to do** with the new todo (e.g., adding it to a list).
223
229
* This keeps `TodoForm`**reusable** – it could work in different apps without modification.
0 commit comments