Skip to content

Commit c870b30

Browse files
docs(store): update createActionGroup guide (#3878)
1 parent 58508e3 commit c870b30

File tree

2 files changed

+84
-35
lines changed

2 files changed

+84
-35
lines changed

projects/ngrx.io/content/guide/store/action-groups.md

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
11
# Action Groups
22

3-
Action groups is a feature to group actions together that belong to the same source. While writing actions, the actions in most of the cases looks like below.
3+
<div class="video-container">
4+
<div class="video-responsive-wrapper">
45

5-
<code-example header="products-page.actions.ts">
6-
import { createAction, props } from '@ngrx/store';
7-
8-
export const opened = createAction('[Products Page] Opened');
6+
<iframe
7+
src="https://www.youtube.com/embed/rk83ZMqEDV4"
8+
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
9+
allowfullscreen
10+
frameborder="0"
11+
></iframe>
912

10-
export const paginationChanged = createAction(
11-
'[Products Page] Pagination Changed',
12-
props&lt;{ page: number; offset: number }&gt;()
13-
);
14-
15-
export const queryChanged = createAction(
16-
'[Products Page] Query Changed',
17-
(query: string) => ({ query })
18-
);
19-
</code-example>
13+
</div>
14+
</div>
2015

21-
22-
In the example we can see that the source (`[Products Page])` is duplicated within each action. With the help of the `createActionGroup` API this can be avoided.
23-
The next example leverages `createActionGroup` to group actions together that belong to the same source. This makes that defining actions is more compact.
16+
The `createActionGroup` function creates a group of action creators with the same source.
17+
It accepts an action group source and an event dictionary as input arguments, where an event is a key-value pair of an event name and event props.
2418

2519
<code-example header="products-page.actions.ts">
2620
import { createActionGroup, emptyProps, props } from '@ngrx/store';
@@ -30,53 +24,88 @@ export const ProductsPageActions = createActionGroup({
3024
events: {
3125
// defining an event without payload using the `emptyProps` function
3226
'Opened': emptyProps(),
33-
27+
3428
// defining an event with payload using the `props` function
3529
'Pagination Changed': props&lt;{ page: number; offset: number }&gt;(),
36-
30+
3731
// defining an event with payload using the props factory
3832
'Query Changed': (query: string) => ({ query }),
39-
}
33+
},
4034
});
4135
</code-example>
4236

43-
To dispatch an action from the group, import the group and invoke an action.
44-
This returns an action that you can then dispatch to the store.
37+
<div class="alert is-helpful">
38+
39+
The `emptyProps` function is used to define an action creator without payload within an action group.
40+
41+
</div>
4542

46-
```typescript
43+
If we create a new action creator using the `createAction` function by copying the previous one but accidentally forget to change its type, the compilation will pass.
44+
Fortunately, this is not the case with the `createActionGroup` function because we will get a compilation error if two actions from the same group have the same type.
45+
46+
The `createActionGroup` function returns a dictionary of action creators where the name of each action creator is created by camel-casing the event name, and the action type is created using the "[Source] Event Name" pattern.
47+
Also, there is no longer a need for barrel files or named imports because the action group can be imported directly into another file.
48+
49+
<code-example header="products.component.ts">
50+
import { Component, inject, OnInit } from '@angular/core';
51+
import { Store } from '@ngrx/store';
4752

4853
import { ProductsPageActions } from './products-page.actions';
4954

5055
@Component({ /* ... */ })
5156
export class ProductsComponent implements OnInit {
52-
constructor(private readonly store: Store) {}
57+
private readonly store = inject(Store);
5358

54-
ngOnInit(): void {
59+
ngOnInit(): void {
5560
// action type: [Products Page] Opened
5661
this.store.dispatch(ProductsPageActions.opened());
5762
}
58-
63+
5964
onPaginationChange(page: number, offset: number): void {
6065
// action type: [Products Page] Pagination Changed
61-
this.store.dispatch(ProductsPageActions.paginationChanged({ page, offset }));
66+
this.store.dispatch(
67+
ProductsPageActions.paginationChanged({ page, offset })
68+
);
6269
}
63-
70+
6471
onQueryChange(query: string): void {
6572
// action type: [Products Page] Query Changed
6673
this.store.dispatch(ProductsPageActions.queryChanged(query));
6774
}
6875
}
76+
</code-example>
77+
78+
## Alternative way of defining event names
79+
80+
In the previous example, event names are defined in the title case format.
81+
In that case, it can be challenging to search for unused action creators because their names are automatically generated by camel-casing the event names.
6982

70-
```
83+
The `createActionGroup` function provides the ability to define event names in the camel case format as well, so action creators will have the same names as events.
84+
This makes it easier to search for their usage within the codebase.
85+
86+
<code-example header="products-api.actions.ts">
87+
import { createActionGroup, props } from '@ngrx/store';
88+
89+
import { Product } from './product.model';
90+
91+
export const ProductsApiActions = createActionGroup({
92+
source: 'Products API',
93+
events: {
94+
productsLoadedSuccess: props&lt;{ products: Product[] }&gt;(),
95+
productsLoadedFailure: props&lt;{ errorMsg: string }&gt;(),
96+
},
97+
});
98+
99+
// generated action creators:
100+
const {
101+
productsLoadedSuccess, // type: "[Products API] productsLoadedSuccess"
102+
productsLoadedFailure, // type: "[Products API] productsLoadedFailure"
103+
} = ProductsApiActions;
104+
</code-example>
71105

72106
## Limitations
73107

74108
An action group uses the event names to create properties within the group that represent the action creators.
75109
The action creator names are generated and are the camelCased version of the event names.
76110
For example, for the event name `Query Changed`, the action creator name will be `queryChanged`.
77111
Therefore, it is not possible to define action creators whose names differ from their event names using the `createActionGroup` function.
78-
79-
You can read more about Action Groups:
80-
81-
- [NgRx Action Group Creator](https://dev.to/ngrx/ngrx-action-group-creator-1deh)
82-
- [Creating Actions with NgRx Just Got Even Easier](https://www.youtube.com/watch?v=rk83ZMqEDV4)

projects/ngrx.io/src/styles/1-layouts/_doc-viewer.scss

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,23 @@
22
// Disable view transition animations.
33
transition: none !important;
44
}
5+
6+
.video-container {
7+
width: 100%;
8+
max-width: 750px;
9+
margin: auto;
10+
}
11+
12+
.video-responsive-wrapper {
13+
position: relative;
14+
padding-bottom: 56.25%; /* 16:9 */
15+
height: 0;
16+
17+
> iframe {
18+
position: absolute;
19+
top: 0;
20+
left: 0;
21+
width: 100%;
22+
height: 100%;
23+
}
24+
}

0 commit comments

Comments
 (0)