Skip to content

aldorn-cg/refresher

 
 

Repository files navigation

NgAdvRefresher

Introduction

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.

further read

content of exercise

What will be done in this exercise?

  1. basic setup of project including redux devtools
  2. adding business functionality in app.component
  3. adding state to the application
    1. root state
    2. business state
  4. displaying state
  5. creating specific selector for state
  6. 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.

1. Basic Setup of ngrx

Check out project

git clone https://github.com/devonfw-ng-adv-training/refresher

Start with initial branch

git checkout 0-start-setup

Install dependencies

npm install 
ng add @ngrx/store
ng add @ngrx/store-devtools

Install Redux Devtools Extension for your favorite browser

Start the Application

ng serve

Confirm successful setup

Check out application state in the browser and confirm @ngrx/state/init in the dev tools

Store initialized succesfullyExample in Google Chrome

Backup branch

backup branch exists as 1-finished-ngrx-setup and will be used in the next step

2. Exercice One: adding a counter to app.component

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

functionalities

Exercise One: functionalities in action

Implement these functionalities to app.component and test the application.

Backup branch

backup branch exists as 2-start-exercise-two and will be used in the next step

3. Exercise Two: setting up a state for counter

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?

reactive-architecture

We will implement this step by step.

  1. Store including State (Exercise Two, part 1 and 2)
  2. View with Selectors (Exercises Three & Four)
  3. Actions (Exercise Five)

Part 1: setting up the root state

create root state (we call it AppState in this project)

  • create file index.ts in src/app/reducers
  • define & export application state (empty interface AppState)
  • define & export root reducer (empty object of ActionReducerMap<AppState>)
  • import root reducer in StoreModule in app.module.ts

Does your application still work? How does the state in Redux Devtools now look like?

Backup branch

backup branch exists as 3-start-exercise-two-pt-two and will be used in the next step

Part 2: setting up the counter state

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.

Doings

  • (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

solution with schematics

(optional) add module

  ng generate module counter --flat false

generate feature store via cli

  ng generate @ngrx/schematics:store counter/Counter -m counter.module.ts

in src/app/counter/reducers/index.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);
      }

in src/app/reducers/index.ts

  • add CounterState to AppState
  • add reducer to reducers

verify result with redux devtools

fire up the application and check out if the value on Redux DevTools is correctly set to initial value of 0

counter-value-initialized

Backup branch

backup branch exists as 4-exercise-three-wiring-up-the-counter and will be used in the next step

4. Exercise Three: wiring up the counter to the state

We now want to use the counter state to display the value

For this we have the following doings:

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 of CounterState in parallel to component value

Backup branch

backup branch exists as 5-exercise-four-using-selectors and will be used in the next step

5. Exercise Four: using ngrx selectors

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.

Doings

  • create feature selector for counter via @ngrx/schematics
  • create specific selector for value of CounterState
  • use selector in counter.component.ts

Backup branch

backup branch exists as 6-exercise-five-using-actions-and-wiring-them and will be used in the next step

6. Exercise Five: using ngrx actions

As a last step we want to be able to manipulate the data in the store. this is possible via actions which we dispatch.

Doings

  • create actions for
    • incrementing
    • decrementing
    • resetting
  • create reducer functions for all actions
  • dispatch actions in counter component

hint: use @ngrx/schematics where possible

Possible solution

et-voila

et voilà le travail 🔥 - We're set for the training!

Backup branch

backup branch exists as 7-ready-for-ng-adv

7. Bonus Round: Use an effect

Backend calls and other asynchronous logic cannot be integrated in a reducer since that is a pure function. ngrx supports that through effects.

Doings

  • 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

backup branch exists as 8-binary-effect (please note that this branch also contains some other structural changes in the application)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 76.7%
  • JavaScript 12.2%
  • HTML 10.1%
  • CSS 1.0%