This repository contains an exercise which you may do to practice some angular basics again. The main focus is on setting up a reactive architecture.
hint: if you don't want to use ngrx, you can also use flux pattern and store the values in subjects.
What will be done in this exercise?
- basic setup of project including redux devtools
- adding business functionality in app.component
- adding state to the application
- root state
- business state
- displaying state
- creating specific selector for state
- creating actions & reducer functions for state changes
If you have trouble during one step, you can cheat by taking a look at the specified backup branch (start with 0-start-setup, result of first step is 1-finished-ngrx-setup, and so on.)
hint: provided solution in backup branch may not be the best possible solution
If there are questions, you can contact one of your trainers or keep them for the training.
git clone https://github.com/devonfw-ng-adv-training/refresher
git checkout 0-start-setup
npm install
Add @ngrx/store & @ngrx/store-devtools to project
ng add @ngrx/store
ng add @ngrx/store-devtools
Install Redux Devtools Extension for your favorite browser
ng serve
Check out application state in the browser and confirm @ngrx/state/init in the dev tools
backup branch exists as 1-finished-ngrx-setup and will be used in the next step
We will want to create a counter functionality to a otherwise empty application. The counter has the following requirements
- display current counter, initial value 0
- increment by +1, +10, +100
- decrement by -1, -10, -100
- reset counter to initial value
Exercise One: functionalities in action
Implement these functionalities to app.component and test the application.
backup branch exists as 2-start-exercise-two and will be used in the next step
As we want to have a reactive architecture, we store the counter state in our store. What do we have to do?
remember this slide?
We will implement this step by step.
- Store including State (Exercise Two, part 1 and 2)
- View with Selectors (Exercises Three & Four)
- Actions (Exercise Five)
create root state (we call it AppState
in this project)
- create file
index.ts
insrc/app/reducers
- define & export application state (empty interface
AppState
) - define & export root reducer (empty object of ActionReducerMap
<AppState
>) - import root reducer in
StoreModule
inapp.module.ts
Does your application still work? How does the state in Redux Devtools now look like?
backup branch exists as 3-start-exercise-two-pt-two and will be used in the next step
hint: for easier setup, you can install and use @ngrx/schematics
ng add @ngrx/schematics
We now want to store the partial state CounterState
in AppState
. You can use schematics for this, or go step by step whatever is your preferred option.
- (optional) create a module for counter state
- create file
counter.reducer.ts
- define & export counter state
- define & export reducer functions
- add state & reducer to AppState & AppReducer
ng generate module counter --flat false
ng generate @ngrx/schematics:store counter/Counter -m counter.module.ts
- rename `State` to `CounterState`
- remove meta reducer
- add initial state
export const initialState: CounterState = {
value: 0
};
- create reducer function
const counterReducer = createReducer(
initialState,
);
export function reducer(state: CounterState | undefined, action: Action) {
return counterReducer(state, action);
}
- add
CounterState
toAppState
- add
reducer
toreducers
fire up the application and check out if the value on Redux DevTools is correctly set to initial value of 0
backup branch exists as 4-exercise-three-wiring-up-the-counter and will be used in the next step
We now want to use the counter state to display the value
For this we have the following doings:
- create counter component
- extract business logic from app component to counter component
- use counter component in app component
- verify stable application
- inject
Store<AppState>
to counter component - display
value
ofCounterState
in parallel to component value
backup branch exists as 5-exercise-four-using-selectors and will be used in the next step
Up next we will create a selector for displaying the value. This has many advantages. One of them is information hiding, so we only get information which is relevant in the specific component. For us it's the value of counter.
- create feature selector for
counter
via @ngrx/schematics - create specific selector for
value
ofCounterState
- use selector in
counter.component.ts
backup branch exists as 6-exercise-five-using-actions-and-wiring-them and will be used in the next step
As a last step we want to be able to manipulate the data in the store. this is possible via actions which we dispatch.
- create actions for
- incrementing
- decrementing
- resetting
- create reducer functions for all actions
- dispatch actions in counter component
hint: use @ngrx/schematics where possible
et voilà le travail 🔥 - We're set for the training!
backup branch exists as 7-ready-for-ng-adv
Backend calls and other asynchronous logic cannot be integrated in a reducer since that is a pure function. ngrx supports that through effects.
- create a service which simulates a backend call to return a binary representation of the value as string
- integrate a call to this service as an effect whenever the value changes
- optionally: create a small component which displays the current value from the store that can be reused everywhere in your application
backup branch exists as 8-binary-effect (please note that this branch also contains some other structural changes in the application)