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
breaking changes: update to Angular/RxJS/Ngrx v6 v6.0.0-beta.1 (johnpapa#147)
* tweak collection reducer methods
* refactor: NgrxDataModule no longer calls store/effects .forFeature,
Inspired by inability to build because of issue
angular/angular#23609
* other refactors to satisfy RxJS v6, fix and add tests, and clear many lint errors.
* feat: add optional label to EntityAction and EntityActionFactory
*`type` - action name, typically generated from the `entityName` and the `op`
28
+
*`type` - action name, typically generated from the `label` and the `op`
28
29
*`entityName` - the name of the entity type
29
30
*`op` - the name of an entity operation
30
31
*`payload?` - the message data for the action.
32
+
*`label?` - the label to use within the generated type. If not specified, the `entityName` is the label.
31
33
*`error?` - an unexpected action processing error.
32
34
33
-
34
35
The `type` is the only property required by _ngrx_. It is a string that uniquely identifies the action among the set of all the types of actions that can be dispatched to the store.
35
36
36
37
_Ngrx-data_ doesn't care about the `type`. It pays attention to the `entityName` and `op` properties.
37
38
38
-
The `entityName` is the name of the entity type.
39
-
It identifies the _entity collection_ in the _ngrx-data_ cache to which this action applies.
39
+
The `entityName` is the name of the entity type.
40
+
It identifies the _entity collection_ in the _ngrx-data_ cache to which this action applies.
40
41
This name corresponds to [_ngrx-data metadata_](entity-metadata.md) for that collection.
41
42
An entity interface or class name, such as `'Hero'`, is a typical `entityName`.
42
43
@@ -47,63 +48,158 @@ that the _ngrx-data_ library can perform.
47
48
The `payload` is conceptually the body of the message.
48
49
Its type and content should fit the requirements of the operation to be performed.
49
50
51
+
The optional `label` appears in the generated `type` text when the `EntityActionFactory` creates this `EntityAction`.
52
+
53
+
The `entityName` is the default label that appears between brackets in the formatted `type`,
54
+
e.g., `'[Hero] ngrx-data/query-all'`.
55
+
50
56
The `error` property indicates that something went wrong while processing the action. [See more below](#action-error).
51
57
52
58
## _EntityAction_ consumers
53
59
54
60
The _ngrx-data_ library ignores the `Action.type`.
55
61
All _ngrx-data_ library behaviors are determined by the `entityName` and `op` properties alone.
56
62
57
-
The _ngrx-data_[`EntityReducer`](../lib/src/reducers/entity-reducer.ts) redirects an action to an `EntityCollectionReducer` based on the `entityName`
63
+
The _ngrx-data_[`EntityReducer`](../lib/src/reducers/entity-reducer.ts) redirects an action to an `EntityCollectionReducer` based on the `entityName`
58
64
and that reducer processes the action based on the `op`.
59
65
60
66
The [`EntityEffects`](../lib/src/effects/entity-effects.ts) intercepts an action if its `op` is among the small set of persistence `EntityAction.op` names.
61
67
The effect picks the right _data service_ for that action's `entityName`, then tells the service to make the appropriate HTTP request and handle the response.
62
68
63
-
64
69
## Creating an _EntityAction_
65
70
66
71
You can create an `EntityAction` by hand if you wish.
67
-
The _ngrx-data_ library considers _any action_ with an `entityName` and `op` properties to be an `EntityAction`.
72
+
The _ngrx-data_ library considers _any action_ with an `entityName` and `op` properties to be an `EntityAction`.
68
73
69
-
The `EntityActionFactory.create()` method helps you create a consistently well-formed `EntityAction` instance
70
-
whose `type` is a string composed from the `entityName` and the `op`.
74
+
The `EntityActionFactory.create()` method helps you create a consistently well-formed `EntityAction` instance
75
+
whose `type` is a string composed from the `label` (the `entityName` by default) and the `op`.
71
76
72
77
For example, the default generated `Action.type` for the operation that queries the server for all heroes is `'[Hero] ngrx-data/query-all'`.
73
78
74
-
>The `EntityActionFactory.create()` method calls the factory's `formatActionType()` method
75
-
to produce the `Action.type` string.
79
+
>The `EntityActionFactory.create()` method calls the factory's `formatActionType()` method
80
+
> to produce the `Action.type` string.
76
81
>
77
-
>Because _ngrx-data_ ignores the `type`, you can replace `formatActionType()` with your own method if you prefer a different format
78
-
or provide and inject your own `EntityActionFactory`.
82
+
> Because _ngrx-data_ ignores the `type`, you can replace `formatActionType()` with your own method if you prefer a different format
83
+
> or provide and inject your own `EntityActionFactory`.
84
+
85
+
Note that **_each entity type has its own \_unique_`Action` for each operation\_**, as if you had created them individually by hand.
86
+
87
+
## Labeling the EntityAction
88
+
89
+
A well-formed action `type` can tell the reader what changed and
90
+
who changed it.
91
+
92
+
The _ngrx-data_ library doesn't look at the type of an `EntityAction`,
93
+
only its `entityName` and `entityOp`.
94
+
So you can get the same behavior from several different actions,
95
+
each with its own informative `type`, as long as they share the same
96
+
`entityName` and `entityOp`.
97
+
98
+
The optional `label` parameter of the `EntityActionFactory.create()` method makes
99
+
it easy to produce meaningful _EntityActions_.
100
+
101
+
You don't have to specify a label. The `entityName` is the default label that appears between brackets in the formatted `type`,
102
+
e.g., `'[Hero] ngrx-data/query-all'`.
103
+
104
+
Here's an example that uses the injectable `EntityActionFactory` to construct the default "query all heroes" action.
105
+
106
+
```
107
+
const action = entityActionFactory<Hero>(
108
+
'Hero', EntityOp.QUERY_ALL, null, 'Load Heroes On Start'
109
+
);
110
+
111
+
store.dispatch(action);
112
+
```
113
+
114
+
Thanks to the _ngrx-data **effects**_, this produces _two_ actions in the log, the first to initiate the request and the second with the successful response:
115
+
116
+
```
117
+
[Hero] ngrx-data/query-all
118
+
[Hero] ngrx-data/query-all-success
119
+
```
120
+
121
+
This default `entityName` label identifies the action's target entity collection.
122
+
But you can't understand the _context_ of the action from these log entries. You don't know who dispatched the action or why.
123
+
The action `type` is too generic.
124
+
125
+
You can create a more informative action by providing a label that
126
+
better describes what is happening and also make it easier to find
127
+
where that action is dispatched by your code.
128
+
129
+
For example,
130
+
131
+
```
132
+
const action = entityActionFactory<Hero>(
133
+
'Hero', EntityOp.QUERY_ALL, null, 'Load Heroes On Start'
134
+
);
135
+
136
+
store.dispatch(action);
137
+
```
138
+
139
+
The action log now looks like this:
140
+
141
+
```
142
+
[Load Heroes On Start] ngrx-data/query-all
143
+
[Load Heroes On Start] ngrx-data/query-all-success
144
+
```
145
+
146
+
### Handcrafted EntityAction
147
+
148
+
You don't have to create entity actions with the `EntityActionFactory`.
149
+
Any action object with an `entityName` and `op` property is
150
+
an entity action, as explained [below](#where-are-the-entityactions).
79
151
80
-
Note that **_each entity type has its own _unique_`Action` for each operation_**, as if you had created them individually by hand.
152
+
The following example creates the initiating "query all heroes" action by hand.
153
+
154
+
```
155
+
const action = {
156
+
type: 'some/arbitrary/action/type',
157
+
entityName: 'Hero',
158
+
op: EntityOp.QUERY_ALL
159
+
};
160
+
161
+
store.dispatch(action);
162
+
```
163
+
164
+
It triggers the HTTP request via _ngrx-data effects_, as in the previous examples.
165
+
166
+
Just be aware that _ngrx-data effects_ uses the `EntityActionFactory` to create the second, success Action.
167
+
Without the `label` property, it produces a generic success action.
168
+
169
+
The log of the two action types will look like this:
170
+
171
+
```
172
+
some/arbitrary/action/type
173
+
[Hero] ngrx-data/query-all-success
174
+
```
175
+
176
+
<aid="where-are-the-entityactions"></a>
81
177
82
178
## Where are the _EntityActions_?
83
179
84
180
In an _ngrx-data_ app, the _ngrx-data_ library creates and dispatches _EntityActions_ for you.
85
181
86
-
_EntityActions_ are largely invisible when you call the [`EntityService`](entity-service.md) API.
182
+
_EntityActions_ are largely invisible when you call the [`EntityService`](entity-service.md) API.
87
183
You can see them in action with the
88
184
[ngrx store dev-tools](https://github.com/ngrx/platform/tree/master/docs/store-devtools).
89
185
90
186
## Why this matters
91
187
92
-
In an ordinary _ngrx_ application, you hand-code every `Action` for every _state_ in the store
93
-
as well as the [reducers](https://github.com/ngrx/platform/blob/master/docs/store/actions.md#action-reducers)
188
+
In an ordinary _ngrx_ application, you hand-code every `Action` for every _state_ in the store
189
+
as well as the [reducers](https://github.com/ngrx/platform/blob/master/docs/store/actions.md#action-reducers)
94
190
that process those _actions_.
95
191
96
192
It takes many _actions_, a complex _reducer_, and the help of the [@ngrx/effects](https://github.com/ngrx/platform/blob/master/docs/effects/README.md) package to manage queries and saves for a _single_ entity type.
97
193
98
194
The [@ngrx/entity](https://github.com/ngrx/platform/blob/master/docs/entity/README.md) package makes the job considerably easier.
99
195
100
-
>The _ngrx-data_ library internally delegates much of the heavy lifting to _@ngrx/entity_.
196
+
>The _ngrx-data_ library internally delegates much of the heavy lifting to _@ngrx/entity_.
101
197
102
198
But you must still write a lot of code for each entity type.
103
-
You're expected to create _eight actions_ per entity type and
199
+
You're expected to create _eight actions_ per entity type and
104
200
write a _reducer_ that responds to these eight actions by calling eight methods of an [@ngrx/entity_EntityAdapter_](https://github.com/ngrx/platform/blob/master/docs/entity/adapter.md#adapter-collection-methods).
105
201
106
-
These artifacts only address the _cached_ entity collection.
202
+
These artifacts only address the _cached_ entity collection.
107
203
108
204
You may write as many as _eighteen additional actions_ to support a typical complement of asynchronous CRUD (Create, Retrieve, Update, Delete) operations. You'll have to dispatch them to the store where you'll process them with more _reducer_ methods and _effects_ that you must also hand code.
109
205
@@ -113,8 +209,8 @@ That's a lot of code to write, test, and maintain.
113
209
With the help of _ngrx-data_, you don't write any of it.
114
210
_Ngrx-data_ creates the _actions_ and the _dispatchers_, _reducers_, and _effects_ that respond to those actions.
115
211
116
-
117
212
<aname="action-error"></a>
213
+
118
214
## _EntityAction.error_
119
215
120
216
The presence of an `EntityAction.error` property indicates that something bad happened while processing the action.
@@ -131,9 +227,10 @@ _Ngrx-data_ traps an error thrown by an `EntityCollectionReducer` and sets the `
131
227
The `error` property is important when the errant action is a _persistence action_ (such as `SAVE_ADD_ONE`).
132
228
The `EntityEffects` will see that such an action has an error and will return the corresponding failure action (`SAVE_ADD_ONE_ERROR`) immediately, without attempting an HTTP request.
133
229
134
-
>This is the only way we've found to prevent a bad action from getting through the effect and triggering an HTTP request.
230
+
>This is the only way we've found to prevent a bad action from getting through the effect and triggering an HTTP request.
0 commit comments