Using a Redux-style Store in Angular 2

a2

I started working with React before Angular 2 and continue to appreciate the technology even though I’m pretty much 100% dedicated to Angular 2 at this time.  One of the early benefits of my venture into React was exposure to the Flux architecture pattern and Redux.  I want to avoid using this blog as a soapbox for architecture rants, so I will simply say that there is a lot to be said for predictable and deterministic application flow among components.  I’m also a fan of avoiding the pitfalls of shared, mutable application state.

If you think the same way, you are either already familiar with React/Redux or perhaps want to read more.  For those in the latter category, you may begin here.  If you are in the former camp and are using/considering Angular 2, you might be interested in Redux-style stores for Angular 2.  I’ve rolled my own models in the past to increase my personal understanding of the concept, but it’s always good to have a third-party framework available for consistency.  Enter @ngrx/store .  Not only does @ngrx/store provide a store that is familiar to Redux users, it is entirely reactive.  So, if you’re on board with RFP in Angular 2, you will feel right at home.

Since we’ve moved into a release candidate and the Angular CLI is in beta, I decided to upgrade and redo the Typescript Math Toolkit Quaternion Calculator using RC1, the Angular CLI, and @ngrx/store .   This version has a new, low-level component to deal with memory operations on the calculator.

In keeping with the general philosophy of ‘store’, the application has one ‘smart’ component. The main calculator component contains the controller logic for the entire calculator. A single, global store represents the state of the calculator at any time.

All other components are children of the main calculator component. Angular 2 provides a natural input/output flow for parent-child components, and it is possible to use either an (output) event emitter or action dispatch to communicate actions from low-level ‘dumb’ components. This demo illustrates both approaches so that you may compare side-by-side.

The calculator consists of three quaternion components (two input and one result), two memory bars (a horizontal area relating to adding/recall from memory) and a clear button, as shown below

qc

The quaternion component representing inputs and result uses an EventEmitter to stream outputs. It may be used in any application, calculator or otherwise, that requires a quaternion. This component is not tied to any concept of a model.

The memory bar currently consists of two buttons, M+ (add to memory) and MR (recall from memory). It’s easy to see text or other visual indicator(s) being added in the future. This component expresses user interaction (clicking either button) by dispatching an action to the store. It can also be integrated into another application, but that application must implement a store. Both components preserve the Flux-style flow of actions moving ‘upward’ either to the model or to a parent component and updates from the store flowing ‘downward’ through subscribers to model updates.

It’s natural to represent the model for the calculator as a simple Object (property bag).  The properties consist of the four values for the two input quaternions, values for quaternions in memory, and the current operation.  A helper class is used to simplify dealing with quaternion values and maintaining immutability in the store.  A single Object reducer (see ObjReducer.ts) is used and only the main component subscribes to updates from the store.

In some demos, you will see the full implementation of the subscriber inside the component constructor.  I prefer to use a constructor for simple setup and nothing else.  The heavy lifting is performed inside class methods.  However, we must be concerned about context in which the handler is executed.  So, for lack of a better term, I created a ‘delegate’ to offload the subscription handler to a class method in the main calculator component’s constructor.

constructor(private _store:Store)
{
  // internal reference to the calculator model
  this._calculator = <Subject<Object>> this._store.select('calculator');

  // subscribe to updates from the calculator (create a 'delegate' to an existing class method)
  this._calculator.subscribe( (calculator:Object) => {this.__update(calculator)});

  // the calculator begins with no active operation
  this._operation = OpEnum.NONE;
}

This is not the only way to implement the subscription, so feel free to modify the code to suit your preferences.

If you are not familiar with integrating third-party code into an application built with the Angular CLI, then study the angular-cli-build.js file from the Github repository.

The calculator functions in a similar manner to previous versions built with React and Polymer.  As long as a valid operation is in progress, the result is updated as new operands are entered.

And, now, you want the code, right?  Well, here it is.  Enjoy and I hope you obtain some useful information on @ngrx/store and how to implement a Flux-style architecture in an application.

Comments are closed.