@@ -169,7 +169,75 @@ MainView = Neo.setupClass(MainView);
169169When you edit the text fields, the ` setState ` call updates the base ` user ` data. The ` Effect ` system detects this,
170170automatically 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
174242The v10 provider was engineered to handle different scopes of state with an intelligent hierarchical model. A child
175243component 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