Skip to content

Commit d3470c3

Browse files
Adds @substore decorator (#412)
This allows for a more declarative use of the ['fractal store' feature](https://github.com/angular-redux/store/blob/master/articles/fractal-store.md) introduced in v6.3.0. Sticking a `@WithSubStore` decorator on a component or service will modify the behaviour of any `@select, @select$, or @dispatch` invocations in instances of that class: ```typescript @WithSubStore({ basePathMethodName: 'getBasePath', localReducer: localReducerFunction, }) @component({ /* ... */ }) class MyFractalComponent { @input() componentId; // Will only be called with the first non-nil value of this.componentId. Subsequent changes to the // input will be ignored. getBasePath() { return [ 'some', 'redux', 'path', this.componentId ]; } // Gets an observable to 'some.redux.path.${this.componentId}.foo' // Under the hood: // ngRedux.configureSubStore( // ['some', 'redux' 'path', this.componentId], // localReducerFunction)).select('foo') @select() foo$: Observable<String>; // Calls substore.dispatch() instead of NgRedux.instance.dispatch(). @dispatch() myAction = () => ({ type: 'MINE' }); } ```
1 parent c79261b commit d3470c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3391
-455
lines changed

.vscode/launch.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
// Use IntelliSense to learn about possible Node.js debug attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "Unit Tests",
11+
"program": "${workspaceRoot}/tests.js"
12+
}
13+
]
14+
}

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 6.5.0
2+
3+
* Enabled fractal store features for the decorator interface. See
4+
https://github.com/angular-redux/store/blob/master/articles/fractal-store.md for details.
5+
16
# 6.4.5
27

38
* Fix a boundary condition where `MockNgRedux` could get instantiated

articles/fractal-store.md

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,63 @@ existing subStore.
9999

100100
## What about @select, @select$, @dispatch?
101101

102-
We don't have decorator support for the fractal store yet. These decorators
103-
act on the global store only right now. We're thinking about a clean way
104-
of doing fractal decorators for a future release.
102+
As of 6.5.0, the decorator interface has been expanded to support fractal
103+
stores as well.
104+
105+
Tag your component or service with the `@WithSubStore` decorator, and a substore will be
106+
configured behind the scenes; instance of that class's `@select`, `@select$`, and `@dispatch` decorators will now operate on that substore instead of the root store. Reworking the
107+
example above with the decorator interface looks like this:
108+
109+
```typescript
110+
interface IUser {
111+
name: string,
112+
occupation: string,
113+
loc: number,
114+
};
115+
116+
export const userComponentReducer = (state, action) =>
117+
action.type === 'ADD_LOC' ?
118+
{ ...state, loc: state.loc + action.payload } :
119+
state;
120+
121+
export const defaultToZero = (obs$: Observable<number>) =>
122+
obs$.map(n => n || 0);
123+
124+
@Component({
125+
selector: 'user',
126+
template: `
127+
<p>name: {{ name$ |async }}</p>
128+
<p>occupation: {{ occupation$ | async }}</p>
129+
<p>lines of code: {{ loc$ | async }}</p>
130+
   <button (click)=addCode(100)>Add 100 lines of code</button>
131+
`,
132+
})
133+
@WithSubStore({
134+
basePathMethodName: 'getBasePath',
135+
localReducer: userComponentReducer,
136+
})
137+
export class UserComponent implements NgOnInit {
138+
@Input() userId: String;
139+
140+
// The substore will be created at the first non-falsy path returned
141+
// from this function.
142+
getBasePath(): PathSelector | null {
143+
return this.userId ? ['users', userId] : null;
144+
}
145+
146+
// These selections are now scoped to the portion of the store rooted
147+
// at ['users', userId];
148+
@select('name') readonly name$: Observable<string>;
149+
@select('occupation') readonly occupation$: Observable<string>;
150+
@select$('loc', defaultToZero) readonly loc$: Observable<number>;
151+
152+
// These dispatches will be scoped to the substore as well, as if you
153+
// had called ngRedux.configureSubStore(...).dispatch(numLines).
154+
@dispatch()
155+
addCode(numLines) {
156+
// Dispatching from the sub-store ensures this component instance's
157+
// subStore only sees the 'ADD_LOC' action.
158+
return { type: 'ADD_LOC', payload: numLines };
159+
}
160+
}
161+
```

docs/assets/js/search.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/classes/devtoolsextension.html

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,9 @@
933933
<li class=" tsd-kind-class">
934934
<a href="ngreduxtestingmodule.html" class="tsd-kind-icon">Ng<wbr>Redux<wbr>Testing<wbr>Module</a>
935935
</li>
936+
<li class=" tsd-kind-interface">
937+
<a href="../interfaces/ifractalstoreoptions.html" class="tsd-kind-icon">IFractal<wbr>Store<wbr>Options</a>
938+
</li>
936939
<li class=" tsd-kind-interface tsd-has-type-parameter">
937940
<a href="../interfaces/observablestore.html" class="tsd-kind-icon">Observable<wbr>Store</a>
938941
</li>
@@ -954,9 +957,15 @@
954957
<li class=" tsd-kind-type-alias">
955958
<a href="../globals.html#transformer" class="tsd-kind-icon">Transformer</a>
956959
</li>
960+
<li class=" tsd-kind-function">
961+
<a href="../globals.html#withsubstore" class="tsd-kind-icon">With<wbr>Sub<wbr>Store</a>
962+
</li>
957963
<li class=" tsd-kind-function">
958964
<a href="../globals.html#dispatch" class="tsd-kind-icon">dispatch</a>
959965
</li>
966+
<li class=" tsd-kind-function">
967+
<a href="../globals.html#enablefractalreducers" class="tsd-kind-icon">enable<wbr>Fractal<wbr>Reducers</a>
968+
</li>
960969
<li class=" tsd-kind-function tsd-has-type-parameter">
961970
<a href="../globals.html#select" class="tsd-kind-icon">select</a>
962971
</li>
@@ -979,6 +988,11 @@ <h3>Hierarchy</h3>
979988
<ul class="tsd-hierarchy">
980989
<li>
981990
<span class="target">DevToolsExtension</span>
991+
<ul class="tsd-hierarchy">
992+
<li>
993+
<a href="mockdevtoolsextension.html" class="tsd-signature-type">MockDevToolsExtension</a>
994+
</li>
995+
</ul>
982996
</li>
983997
</ul>
984998
</section>
@@ -1008,7 +1022,7 @@ <h3>enhancer</h3>
10081022
<li class="tsd-description">
10091023
<aside class="tsd-sources">
10101024
<ul>
1011-
<li>Defined in <a href="https://github.com/SethDavenport/ng2-redux/blob/0584dc5/src/components/dev-tools.ts#L26">src/components/dev-tools.ts:26</a></li>
1025+
<li>Defined in <a href="https://github.com/SethDavenport/ng2-redux/blob/0dbbb4f/src/components/dev-tools.ts#L26">src/components/dev-tools.ts:26</a></li>
10121026
</ul>
10131027
</aside>
10141028
<div class="tsd-comment tsd-typography">
@@ -1038,7 +1052,7 @@ <h3>is<wbr>Enabled</h3>
10381052
<li class="tsd-description">
10391053
<aside class="tsd-sources">
10401054
<ul>
1041-
<li>Defined in <a href="https://github.com/SethDavenport/ng2-redux/blob/0584dc5/src/components/dev-tools.ts#L51">src/components/dev-tools.ts:51</a></li>
1055+
<li>Defined in <a href="https://github.com/SethDavenport/ng2-redux/blob/0dbbb4f/src/components/dev-tools.ts#L51">src/components/dev-tools.ts:51</a></li>
10421056
</ul>
10431057
</aside>
10441058
<div class="tsd-comment tsd-typography">

docs/classes/mockdevtoolsextension.html

Lines changed: 62 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -913,10 +913,10 @@
913913
<li class="current tsd-kind-class">
914914
<a href="mockdevtoolsextension.html" class="tsd-kind-icon">Mock<wbr>Dev<wbr>Tools<wbr>Extension</a>
915915
<ul>
916-
<li class=" tsd-kind-property tsd-parent-kind-class tsd-is-inherited">
916+
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-inherited">
917917
<a href="mockdevtoolsextension.html#enhancer" class="tsd-kind-icon">enhancer</a>
918918
</li>
919-
<li class=" tsd-kind-property tsd-parent-kind-class tsd-is-inherited">
919+
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-inherited">
920920
<a href="mockdevtoolsextension.html#isenabled" class="tsd-kind-icon">is<wbr>Enabled</a>
921921
</li>
922922
</ul>
@@ -933,6 +933,9 @@
933933
<li class=" tsd-kind-class">
934934
<a href="ngreduxtestingmodule.html" class="tsd-kind-icon">Ng<wbr>Redux<wbr>Testing<wbr>Module</a>
935935
</li>
936+
<li class=" tsd-kind-interface">
937+
<a href="../interfaces/ifractalstoreoptions.html" class="tsd-kind-icon">IFractal<wbr>Store<wbr>Options</a>
938+
</li>
936939
<li class=" tsd-kind-interface tsd-has-type-parameter">
937940
<a href="../interfaces/observablestore.html" class="tsd-kind-icon">Observable<wbr>Store</a>
938941
</li>
@@ -954,9 +957,15 @@
954957
<li class=" tsd-kind-type-alias">
955958
<a href="../globals.html#transformer" class="tsd-kind-icon">Transformer</a>
956959
</li>
960+
<li class=" tsd-kind-function">
961+
<a href="../globals.html#withsubstore" class="tsd-kind-icon">With<wbr>Sub<wbr>Store</a>
962+
</li>
957963
<li class=" tsd-kind-function">
958964
<a href="../globals.html#dispatch" class="tsd-kind-icon">dispatch</a>
959965
</li>
966+
<li class=" tsd-kind-function">
967+
<a href="../globals.html#enablefractalreducers" class="tsd-kind-icon">enable<wbr>Fractal<wbr>Reducers</a>
968+
</li>
960969
<li class=" tsd-kind-function tsd-has-type-parameter">
961970
<a href="../globals.html#select" class="tsd-kind-icon">select</a>
962971
</li>
@@ -971,7 +980,7 @@
971980
<h3>Hierarchy</h3>
972981
<ul class="tsd-hierarchy">
973982
<li>
974-
<span class="tsd-signature-type">DevToolsExtension</span>
983+
<a href="devtoolsextension.html" class="tsd-signature-type">DevToolsExtension</a>
975984
<ul class="tsd-hierarchy">
976985
<li>
977986
<span class="target">MockDevToolsExtension</span>
@@ -985,93 +994,70 @@ <h2>Index</h2>
985994
<section class="tsd-panel tsd-index-panel">
986995
<div class="tsd-index-content">
987996
<section class="tsd-index-section tsd-is-inherited">
988-
<h3>Properties</h3>
997+
<h3>Methods</h3>
989998
<ul class="tsd-index-list">
990-
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><a href="mockdevtoolsextension.html#enhancer" class="tsd-kind-icon">enhancer</a></li>
991-
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><a href="mockdevtoolsextension.html#isenabled" class="tsd-kind-icon">is<wbr>Enabled</a></li>
999+
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><a href="mockdevtoolsextension.html#enhancer" class="tsd-kind-icon">enhancer</a></li>
1000+
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><a href="mockdevtoolsextension.html#isenabled" class="tsd-kind-icon">is<wbr>Enabled</a></li>
9921001
</ul>
9931002
</section>
9941003
</div>
9951004
</section>
9961005
</section>
9971006
<section class="tsd-panel-group tsd-member-group tsd-is-inherited">
998-
<h2>Properties</h2>
999-
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-class tsd-is-inherited">
1007+
<h2>Methods</h2>
1008+
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-inherited">
10001009
<a name="enhancer" class="tsd-anchor"></a>
10011010
<h3>enhancer</h3>
1002-
<div class="tsd-signature tsd-kind-icon">enhancer<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">function</span></div>
1003-
<aside class="tsd-sources">
1004-
<p>Inherited from DevToolsExtension.enhancer</p>
1005-
<ul>
1006-
<li>Defined in lib/src/components/dev-tools.d.ts:20</li>
1007-
</ul>
1008-
</aside>
1009-
<div class="tsd-comment tsd-typography">
1010-
<div class="lead">
1011-
<p>A wrapper for the Chrome Extension Redux DevTools.
1012-
Makes sure state changes triggered by the extension
1013-
trigger Angular2&#39;s change detector.</p>
1014-
</div>
1015-
<dl class="tsd-comment-tags">
1016-
<dt>argument</dt>
1017-
<dd><p>options: dev tool options; same
1018-
format as described here:
1019-
[zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md]</p>
1020-
</dd>
1021-
</dl>
1022-
</div>
1023-
<div class="tsd-type-declaration">
1024-
<h4>Type declaration</h4>
1025-
<ul class="tsd-parameters">
1026-
<li class="tsd-parameter-siganture">
1027-
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported">
1028-
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>options<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Object</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></li>
1029-
</ul>
1030-
<ul class="tsd-descriptions">
1031-
<li class="tsd-description">
1032-
<h4 class="tsd-parameters-title">Parameters</h4>
1033-
<ul class="tsd-parameters">
1034-
<li>
1035-
<h5><span class="tsd-flag ts-flagOptional">Optional</span> options: <span class="tsd-signature-type">Object</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">undefined</span></h5>
1036-
</li>
1037-
</ul>
1038-
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">any</span></h4>
1039-
</li>
1011+
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class tsd-is-inherited">
1012+
<li class="tsd-signature tsd-kind-icon">enhancer<span class="tsd-signature-symbol">(</span>options<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Object</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></li>
1013+
</ul>
1014+
<ul class="tsd-descriptions">
1015+
<li class="tsd-description">
1016+
<aside class="tsd-sources">
1017+
<p>Inherited from <a href="devtoolsextension.html">DevToolsExtension</a>.<a href="devtoolsextension.html#enhancer">enhancer</a></p>
1018+
<ul>
1019+
<li>Defined in <a href="https://github.com/SethDavenport/ng2-redux/blob/0dbbb4f/src/components/dev-tools.ts#L26">src/components/dev-tools.ts:26</a></li>
10401020
</ul>
1041-
</li>
1042-
</ul>
1043-
</div>
1021+
</aside>
1022+
<div class="tsd-comment tsd-typography">
1023+
<div class="lead">
1024+
<p>A wrapper for the Chrome Extension Redux DevTools.
1025+
Makes sure state changes triggered by the extension
1026+
trigger Angular2&#39;s change detector.</p>
1027+
</div>
1028+
</div>
1029+
<h4 class="tsd-parameters-title">Parameters</h4>
1030+
<ul class="tsd-parameters">
1031+
<li>
1032+
<h5><span class="tsd-flag ts-flagOptional">Optional</span> options: <span class="tsd-signature-type">Object</span></h5>
1033+
</li>
1034+
</ul>
1035+
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">any</span></h4>
1036+
</li>
1037+
</ul>
10441038
</section>
1045-
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-class tsd-is-inherited">
1039+
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-inherited">
10461040
<a name="isenabled" class="tsd-anchor"></a>
10471041
<h3>is<wbr>Enabled</h3>
1048-
<div class="tsd-signature tsd-kind-icon">is<wbr>Enabled<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">function</span></div>
1049-
<aside class="tsd-sources">
1050-
<p>Inherited from DevToolsExtension.isEnabled</p>
1051-
<ul>
1052-
<li>Defined in lib/src/components/dev-tools.d.ts:24</li>
1053-
</ul>
1054-
</aside>
1055-
<div class="tsd-comment tsd-typography">
1056-
<div class="lead">
1057-
<p>Returns true if the extension is installed and enabled.</p>
1058-
</div>
1059-
</div>
1060-
<div class="tsd-type-declaration">
1061-
<h4>Type declaration</h4>
1062-
<ul class="tsd-parameters">
1063-
<li class="tsd-parameter-siganture">
1064-
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported">
1065-
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></li>
1042+
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class tsd-is-inherited">
1043+
<li class="tsd-signature tsd-kind-icon">is<wbr>Enabled<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">any</span></li>
1044+
</ul>
1045+
<ul class="tsd-descriptions">
1046+
<li class="tsd-description">
1047+
<aside class="tsd-sources">
1048+
<p>Inherited from <a href="devtoolsextension.html">DevToolsExtension</a>.<a href="devtoolsextension.html#isenabled">isEnabled</a></p>
1049+
<ul>
1050+
<li>Defined in <a href="https://github.com/SethDavenport/ng2-redux/blob/0dbbb4f/src/components/dev-tools.ts#L51">src/components/dev-tools.ts:51</a></li>
10661051
</ul>
1067-
<ul class="tsd-descriptions">
1068-
<li class="tsd-description">
1069-
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">any</span></h4>
1070-
</li>
1071-
</ul>
1072-
</li>
1073-
</ul>
1074-
</div>
1052+
</aside>
1053+
<div class="tsd-comment tsd-typography">
1054+
<div class="lead">
1055+
<p>Returns true if the extension is installed and enabled.</p>
1056+
</div>
1057+
</div>
1058+
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">any</span></h4>
1059+
</li>
1060+
</ul>
10751061
</section>
10761062
</section>
10771063
<footer class="with-border-bottom">

0 commit comments

Comments
 (0)