Skip to content

Commit 71b47bc

Browse files
committed
#7094 formula with mixed provider data example
1 parent fda213c commit 71b47bc

1 file changed

Lines changed: 69 additions & 2 deletions

File tree

learn/blog/v10-deep-dive-state-provider.md

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,75 @@ MainView = Neo.setupClass(MainView);
169169
When you edit the text fields, the `setState` call updates the base `user` data. The `Effect` system detects this,
170170
automatically re-runs the `fullName` formula, and updates the welcome label.
171171

172-
### 4. Hierarchical by Design: Nested Providers That Just Work
172+
### 4. Formulas Across Hierarchies
173+
174+
The true power of the hierarchical system is revealed when formulas in a child provider can seamlessly use data from a
175+
parent. This allows you to create powerful, scoped calculations that still react to global application state.
176+
177+
```javascript live-preview
178+
import Button from 'neo.mjs/src/button/Base.mjs';
179+
import Container from 'neo.mjs/src/container/Base.mjs';
180+
import Label from 'neo.mjs/src/component/Label.mjs';
181+
182+
class MainView extends Container {
183+
static config = {
184+
className: 'My.StateProvider.Example4',
185+
layout: {ntype: 'vbox', align: 'stretch', padding: '10px'},
186+
// 1. Parent provider with a global tax rate
187+
stateProvider: {
188+
data: {
189+
taxRate: 0.19
190+
}
191+
},
192+
items: [{
193+
module: Label,
194+
bind: { text: data => `Global Tax Rate: ${data.taxRate * 100}%` }
195+
}, {
196+
module: Button,
197+
text: 'Change Tax Rate',
198+
handler() {
199+
this.setState({taxRate: Math.random().toFixed(2)});
200+
},
201+
style: {marginBottom: '10px'}
202+
}, {
203+
module: Container,
204+
// 2. Child provider with a local price
205+
stateProvider: {
206+
data: {
207+
price: 100
208+
},
209+
formulas: {
210+
// 3. This formula uses data from BOTH providers
211+
totalPrice: data => data.price * (1 + data.taxRate)
212+
}
213+
},
214+
style: {padding: '10px'},
215+
layout: {ntype: 'vbox', align: 'start'},
216+
items: [{
217+
module: Label,
218+
bind: { text: data => `Local Price: €${data.price.toFixed(2)}` }
219+
}, {
220+
module: Label,
221+
bind: { text: data => `Total (inc. Tax): €${data.totalPrice.toFixed(2)}` },
222+
style: {fontWeight: 'bold', marginTop: '10px'}
223+
}, {
224+
module: Button,
225+
text: 'Change Price',
226+
handler() {
227+
this.setState({price: Math.floor(Math.random() * 100) + 50});
228+
},
229+
style: {marginTop: '10px'}
230+
}]
231+
}]
232+
}
233+
}
234+
MainView = Neo.setupClass(MainView);
235+
```
236+
In this example, the child provider's `totalPrice` formula depends on its own local `price` and the parent's `taxRate`.
237+
Clicking either button triggers the correct reactive update, and the total price is always in sync. This demonstrates
238+
the effortless composition of state across different parts of your application.
239+
240+
### 5. Hierarchical by Design: Nested Providers That Just Work
173241

174242
The v10 provider was engineered to handle different scopes of state with an intelligent hierarchical model. A child
175243
component can seamlessly access data from its own provider as well as any parent provider.
@@ -193,7 +261,6 @@ class MainView extends Container {
193261
stateProvider: {
194262
data: { user: 'Alice' }
195263
},
196-
border: true,
197264
style: {padding: '10px', marginTop: '10px'},
198265
items: [{
199266
module: Label,

0 commit comments

Comments
 (0)