Skip to main content

Angular NgRx: A Simple Action

Greetings!

This is our second article on our simple NgRx series. As we saw how to read stored value from the Store, let's see how we can change the value using Actions in this article. Yet again, this will be another simple working example.

Full working example https://github.com/slmanju/ngrx-at-slmanju/blob/main/ngrx-hello-action
"Red Light, Green Light" ;)

What we need

  • Store initial value
  • Define actions to change it
  • Create reducers to react on the action changes
  • Register the reducer
  • Read, change values

Generate the Project

ng new ngrx-hello-action --routing=false --style=css
cd ngrx-hello-action/
ng add @ngrx/store@latest
ng serve
As this is to demonstrate, we will add Store realted code in a single file.

Initial Value

In this example, we will store color value and change it.
export const initialState: string = 'red';

Create Action

Let us create our red and green actions.
export const red = createAction('[Color] Red');
export const green = createAction('[Color] Green');
To simplify NgRx operations, Angular has introduced createXX functions. Which is easier to use. However, you will encounter Action interface a lot in tutorials as this is relatively new. As the technology rapidly changing, always look for the documentation.

We have use Angular's createAction function to create our Red and Green actions. Comparing to older way, this is super nice.

Create Reducer

Let's create our reducer with red and green actions.
const _colorReducer = createReducer(
  initialState,
  on(red, (state) => 'red'),
  on(green, (state) => 'green')
);

export function colorReducer(state: string = initialState, action: Action) {
  return _colorReducer(state, action);
}
Just like the action, we have createReducer to create reducers. Which also much simpler to previous switch based reduders. Using the 'on' operator, we are providing our state changes related to actions. Here for example,

on the action green, store the value 'green'.

Complete file as of ngrx-hello-action/src/app/color.reducer.ts ;
import { Action, createAction, createReducer, on } from '@ngrx/store';

export const red = createAction('[Color] Red');
export const green = createAction('[Color] Green');

export const initialState: string = 'red';

const _colorReducer = createReducer(
  initialState,
  on(red, (state) => 'red'),
  on(green, (state) => 'green')
);

export function colorReducer(state: string = initialState, action: Action) {
  return _colorReducer(state, action);
}

Register the Reducer

Now we need to register our reducer.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { colorReducer } from './color.reducer';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    StoreModule.forRoot({
      color: colorReducer
    }, {})
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Note that we have registered our reducer with the name 'color' (color: colorReducer), our value will be stored under the name color as a string like { color: string }
ex: { color: 'red' }

Read, Change the Value

We can access our slice from store using registered 'color' property.
color$: Observable<string>;

constructor(private colorStore: Store<{ color: string }>) {
this.color$ = colorStore.select('color');
}

Dispatch an Action

With the action we created using create function, we can easily dispatch using it.
this.colorStore.dispatch(red());
import { green, red } from './color.reducer';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  color$: Observable<string>;
  
  constructor(private colorStore: Store<{ color: string }>) {
    this.color$ = colorStore.select('color');
  }

  red() {
    this.colorStore.dispatch(red());
  }

  green() {
    this.colorStore.dispatch(green());
  }

}
We are listening to two button click events with red() and green() functions. Also note that in our actions, we are not passing any value for the simplicity of the example.

Create the Template

As the final step, let's add our buttons to dispatch the actions and show the stored value.
<div class="hello">
  <button (click)="red()">Red</button>
  <button (click)="green()">Green</button>

  <div>Color: {{ color$ | async }}</div>
</div>
If you have come this far, congratulations on your simplest action ;). Let's see how we can pass a value from the component and store an object in next article.

Happy coding ;)