
In the current application development era, Single Page Application (SPA) is a great feature to develop modern web-based applications. In these SPA applications, we tend to move the data level dependency from the server side to browser level as much as possible to improve the application performance. So as much as the application-level functionality moves to the browser level, the amount of the data and ways to manage the data are also increased. Modern SPA application frameworks like Angular, React use component-based architecture that divides our application into small sections. Each component contains its own HTML page, stylesheet, and its own state (data). This approach is very efficient because it divides our application into small sections that we can manage very easily and also, we can reuse these components into our application.
The component-based architecture is very feasible if the size of our application is not very large. When the size of our application is increased, it becomes very difficult to maintain the state of each component. Let’s focus on some downsides of the component-based architecture.
- Data Passing Approach using Properties
In Angular, we use the input properties to pass the data in component tree. Suppose, we have a component in component tree and we want to pass some data to its grand children component; First of all, we have to pass this data to its child component that is parent component of the “grand children” components, then further, the “parent” component passes that data to its own children components (grandchildren) using the “input” property.
It is clear that in the above process, the parent component doesn’t use this data but if we want to pass the data to the grandchildren components, we must have to use this intermediate component. In a component-based architecture, we have many intermediate components for passing the data but not actually using that data. So, this approach is not very efficient.
- Inflexible Components
Using this property of passing the data b/w components, make the components inflexible and we can’t reuse them because we will have to pass several input values, which makes it difficult to understand the assignment of a component.
- Maintenance of data Synchronously
If multiple components are using the same states and state changes within one component, then it is necessary to notify all the other components to update their state too. That is very difficult and expensive task.
- State of Application
If each component contains its own state, then it becomes very difficult to take a screenshot of the state of whole application because we have divided the state at the component level.
- Redundant Data
If we have multiple components and each component contains its own copy of data (state), then there are huge chances that some duplicate data is present in multiple components.
All the above shortcoming can lead an application to inconsistent state application and makes it difficult to manage the state of the whole application. To overcome all these shortcomings, we need a new way, using which, we can manage the state of our application.
Redux is a predictable state container for the JavaScript apps. It is an open-source JavaScript library developed to maintain the state of the application. Redux works on the centralized data mechanism that means instead of storing the state at the component level, we store the state in a centralized location and all the components can access this store. Sometimes, the data architecture becomes a complex topic for the application but the advantage of Redux is that it makes the data architecture very easy.
Redux Architecture

Redux works on following key points.
- Maintain the whole application data into a single state and we can access the state from the store of application.
- This store doesn't mutate directly.
- Action is used to trigger the change in the state of the application.
- Action calls the dispatcher.
- Dispatcher calls the Reducer that takes the previous state and new data as input and generates a new state and now, all the components use this new state.
Building Blocks of Redux
Before starting the development with Redux, we must have the basic knowledge of the building blocks or working blocks of the Redux architecture. Let’s understand them.
Store
Store is a simple JavaScript object that contains the state of the whole application. We can update the state of the application using the “dispatch(action, payload)” method. Dispatcher updates the previous state o the application and generates a new state every time.
Actions
Actions are payloads of the information that are sent from our application to our store. Actions are the source to send the data to the store using the “Store.dispatch()” method. We can compare the action to events that indicate the reducer what to perform with this new data and the previous state.
Reducers
Action tells the Reducer to what to perform but doesn’t tell how to perform the task. Reducers are the functions that specify how the state will change. Reducer is a pure function; that means, we get the same output with same input in all the conditions and circumstances. Reducer takes the action name and previous state and always returns a new state to contain the data with modification included.
API
APIs are the ways to interact with the external environment. API is used to get the data from server side and also update the data to server side.
I think the above intro is enough to start working with Redux and we will cover the remaining topic later in this article. If you want to read more about Redux, then go to the official website of Redux here.
Create Bug Todo List Application with Angular and Redux
Now, let us start developing the bug todo list application using the Angular 4 and use the Redux to maintain the state of our application. Actually the “bug todo” app will be a demo of the bug management system, where we can add the news bugs, check the status of the bugs and also add the functionality to change the status of the bugs.
To create a new Angular 4 application, we will use the Angular CLI. Open a new command line terminal and run the “ng new Bug-TodoApp” this command create a new Angular 4 template for the project.
Now open this project into any Code Editor here I am using the “Visual Studio Code”. Move to the root directory of the project and run the “ng serve” command this command build and run our project at 4200 port with live reloading features. If your using the “Visual Studio Code” then you can also use the “integrated Terminal” from View menu to run the commands.

Now open the given URL into any browser and you will find the below screen.

Install Redux Packages
After successfully creating the Angular template now we need to install the “redux” packages for our application. So run the “npm install redux @angular-redux/store --save” command to install the required packages. Now you go to the “package.json” file you will find both packages have been added to our project. After installing the Redux package now we create building blocks like Store, Action and Reducer for our application.
Create IBugModel Model
Now we create a model for our bugtodo project. For this we create an Interface with some property. First of all create a “model” folder into “src” directory and add “BugModel.ts” file into this directory. After adding the TypeScript file now paste the following code into this file.
- export interface IBugModel{
- bugId:number;
- description:string;
- project:string;
- priority:string;
- status:string;
- }
Create Store
Add a folder into “Src” directory and named this folder as “store”, now in this folder add a typescript file and named this field as “BugStore.ts”. After creating this file now paste following code into this file.
- import { IBugModel } from "../model/BugModel";
- export interface IBugState {
- bugList:IBugModel[],
- totalBug:number,
- unassigned:number,
- assignedBug:number,
- pendingBug:number,
- completed:number,
- reopenBug:number,
- bugId:number
- }
- export const INITIAL_STATE:IBugState={
- bugList:[],
- totalBug:0,
- unassigned:0,
- assignedBug:0,
- pendingBug:0,
- completed:0,
- reopenBug:0,
- bugId:0
- }
In the above lines of code we create an “IBugStore” interface and this interface will work as the store of the our application state .
The “bugList” property will contain the list of all bug and “unassigned”, “assigned”, “pending”, “completed” and “reopenBug” property indicate the numbers of unassigned, assigned, pending, completed and reopen bugs.
We also create an “INITIAL_STATE” constant of type “IBugState” this variable indicate the initial state of the application whenever our application run the first time. If we are creating a state for the application then we also need to define the initial state of the application that will load when application runs the first time.
Create Action
As Redux document describes that “Actions” are used to indicate to the reducer what type of task it will perform with the payload. Now we create a file that will define all possible “Action” types. So create an “action” folder into “src” directory, after creating the folder now create a “BugAction.ts” file into this folder and paste the following code into this file.
- export class bugTodoAction{
- public static Add_NewBug='Add';
- public static Assign_Bug='Assign';
- public static Reopen_Bug='Reopen';
- public static Close_Bug='Close';
- public static Pending_Bug='Pending';
- public static Remove_All='Remove_All';
- public static Open_Model='Open_Model';
- }
Create Reducer
Reducer is the heart of the “Redux” pattern, each reducer function takes two parameters, the first parameter contains the previous state of the application and the second parameter contains the action type and new data payload for the state change. Now create a “reducer” folder into “src” directory and create a “Reducer.ts” file and paste the following code into this file.
- import {bugTodoAction} from "../action/BugAction";
- export function rootReducre(state,action){
- switch(action.type){
- case bugTodoAction.Add_NewBug:
- action.todo.bugId=state.bugList.length+1;
- action.todo.status="Unassigned";
- return Object.assign({},state,{
- bugList:state.bugList.concat(Object.assign({},action.todo)),
- totalBug:state.bugList.length+1,
- unassigned:state.unassigned+1,
- assignedBug:state.assignedBug,
- pendingBug:state.pendingBug,
- completed:state.completed,
- reopenBug:state.completed
- });
- case bugTodoAction.Assign_Bug:
- var bug=state.bugList.find(x=>x.bugId==action.bugNo);
- var currentStatus=bug.status;
- var index =state.bugList.indexOf(bug);
- if(bug.status=="Unassigned"){
- state.unassigned--;
- }
- else if(bug.status=="Reopen"){
- state.reopenBug--;
- }
- else if(bug.status=="Close"){
- state.completed--;
- }
- else if(bug.status=="Pending"){
- state.pendingBug--;
- }
- if(bug.status!="Assign"){
- state.assignedBug++;
- }
- bug.status=bugTodoAction.Assign_Bug;
- return Object.assign({},state,{
- bugList:[
- ...state.bugList.slice(0,index),
- Object.assign({},bug),
- ...state.bugList.slice(index+1)
- ]
- });
- case bugTodoAction.Close_Bug:
- var bug=state.bugList.find(x=>x.bugId==action.bugNo);
- var currentStatus=bug.status;
- var index =state.bugList.indexOf(bug);
- if(bug.status=='Assign'){
- state.assignedBug--;
- }
- else if(bug.status=="Unassigned"){
- state.unassigned--;
- }
- else if(bug.status=="Reopen"){
- state.reopenBug--;
- }
- else if(bug.status=="Pending"){
- state.pendingBug--;
- }
- if(bug.status!="Close"){
- state.completed++;
- }
- bug.status=bugTodoAction.Close_Bug;
- return Object.assign({},state,{
- bugList:[
- ...state.bugList.slice(0,index),
- Object.assign({},bug),
- ...state.bugList.slice(index+1)
- ],
- lastUpdate:new Date()
- });
- case bugTodoAction.Pending_Bug:
- var bug=state.bugList.find(x=>x.bugId==action.bugNo);
- var currentStatus=bug.status;
- var index =state.bugList.indexOf(bug);
- if(bug.status=='Assign'){
- state.assignedBug--;
- }
- else if(bug.status=="Unassigned"){
- state.unassigned--;
- }
- else if(bug.status=="Reopen"){
- state.reopenBug--;
- }
- else if(bug.status=="Close"){
- state.completed--;
- }
- if(bug.status!="Pending"){
- state.pendingBug++;
- }
- bug.status=bugTodoAction.Pending_Bug;
- return Object.assign({},state,{
- bugList:[
- ...state.bugList.slice(0,index),
- Object.assign({},bug),
- ...state.bugList.slice(index+1)
- ],
- lastUpdate:new Date()
- });
- case bugTodoAction.Remove_All:
- return Object.assign({},state,{
- bugList:[],
- totalBug:0,
- unassigned:0,
- assignedBug:0,
- pendingBug:0,
- completed:0,
- reopenBug:0
- });
- case bugTodoAction.Reopen_Bug:
- var bug=state.bugList.find(x=>x.bugId==action.bugNo);
- var currentStatus=bug.status;
- var index =state.bugList.indexOf(bug);
- if(bug.status=='Assign'){
- state.assignedBug--;
- }
- else if(bug.status=="Unassigned"){
- state.unassigned--;
- }
- else if(bug.status=="Pending"){
- state.pendingBug--;
- }
- else if(bug.status=="Close"){
- state.completed--;
- }
- if(bug.status!="Reopen"){
- state.reopenBug++;
- }
- bug.status=bugTodoAction.Reopen_Bug;
- return Object.assign({},state,{
- bugList:[
- ...state.bugList.slice(0,index),
- Object.assign({},bug),
- ...state.bugList.slice(index+1)
- ],
- lastUpdate:new Date()
- });
- case bugTodoAction.Open_Model:
- return Object.assign({},state,{
- bugId:action.bugId
- });
- }
- return state;
- }
We create a “rootRedcuer” function that takes the two parameter and using the switch statement we define all the action blocks that are defined into “bugTodoAction.ts” file. I know it is a little bit difficult to understand the above code but don’t worry we will cover all these methods and their functionalities into upcoming part of the article. If your application is small then you can create a single reducer and define all the action into this single reducer function but if application is very large then you can create multiple reducer function and later combine all the reducer function into a single unit. Here we will use a single reducer method.
So far we have configured all the building block(Action, Store, Reducer) of the “Redux” pattern let’s implement this Redux pattern into application.
Open the “app.module.ts” file and replace the code with below lines of code.
- import { BrowserModule } from '@angular/platform-browser';
- import { NgModule } from '@angular/core';
- import { AppComponent } from './app.component';
- import {FormsModule} from "@angular/forms";
- import {NgRedux,NgReduxModule} from "@angular-redux/store";
- import { IBugState, INITIAL_STATE } from '../store/BugStore';
- import { rootReducre } from '../reducer/Reducer';
- @NgModule({
- declarations: [
- AppComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- NgReduxModule
- ],
- providers: [],
- bootstrap: [AppComponent]
- })
- export class AppModule {
- constructor(ngRedux:NgRedux<IBugState>){
- ngRedux.configureStore(rootReducre,INITIAL_STATE);
- }
- }
In the above line of code we import some “modules” and add the “NgReduxModule” into imports array. In constructor function we configure the state for the application using the “NgRedux” and also configure the “reducer” function that will handle all the actions. In “configureStore” function of “ngRedux” class we pass the reducer function name and the initial state of the application.
Define the Layout for application
So far we have configured all the Redux configuration blocks, define the state and reducer function for the state into “AppModule.ts” file, I think all major tasks have been completed, now we only need to define the view of our application and perform the required action.
Add Bootstrap 4 Configuration
We will use the “Bootstrap 4” for design purposes so open the “index.html” file and paste the following links into title section.
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
- <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
If you are new to Bootstrap 4 or want to read more about the Bootstrap 4 then you can go to the official website of the bootstrap, following is the link here.
Add Required Component
Open the command line terminal and run the “ng g c bugTodo” command; this command adds a new component in your project. In this component we will write the code to add a new bug or clear all bug lists. After adding this component now we add an another component, so run the “ng g c bugStatus” command, this command adds a new component and name this component as “bug-status.component.ts”. We will use this component to show the status of the bugs. We also show the list of all bugs that are generated so far. To add another component run the “ng g c bugList” command. This command adds a component as “bug-list.component.ts” in our project. After generating all three components following will be the structure of the project.
Design Layout of the application
After creating the all the required components now we design the layout of the application. Open the “app.component.html” file replace the code with following code.
App.component.html
- <main role="main" class="container">
- <div class="row row-offcanvas row-offcanvas-right">
- <div class="col-12 col-md-9">
- <app-bug-todo></app-bug-todo>
- <app-bug-list></app-bug-list>
- </div>
- <div class="col-6 col-md-3 sidebar-offcanvas" id="sidebar">
- <app-bug-status></app-bug-status>
- </div>
- </div>
- <hr>
- </main>
In the same way replace the code of all the remaining components,
bug-todo.component.html
- <div class="card">
- <h4 class="card-header">Bug Dashboard</h4>
- <div class="card-body">
- <h4 class="card-title">Add new bug</h4>
- <form >
- <div class="form-row">
- <div class="col-auto">
- <input
- type="text" class="form-control"
- placeholder="Description" id="description"
- name="description"
- />
- </div>
- <div class="col-auto">
- <select
- type="text" class="form-control"
- placeholder="Priority" id="reprioritysponsible"
- name="priority"
- >
- <option value="Bike">Bike</option>
- <option value="Car">Car</option>
- <option value="Health">Health</option>
- <option value="Home">Home</option>
- <option value="ProHealth">ProHealth</option>
- </select>
- </div>
- <div class="col-auto">
- <select
- type="text" class="form-control"
- placeholder="Priority" id="reprioritysponsible"
- name="priority"
- >
- <option value="Low">Low</option>
- <option value="Medium">Medium</option>
- <option value="High">High</option>
- </select>
- </div>
- <div class="col-auto">
- <button type="submit" class="btn btn-info">Add Bug</button>
- </div>
- </div>
- </form>
- <br/>
- <a href="#" class="btn btn-danger">Clear List</a>
- </div>
- </div>
















Hadshana KamalanathanPosted Jul 15, 2018, 12:39 PM
Thank you for sharing