Code Monkey home page Code Monkey logo

angular2-redux-chat's Introduction

Angular 2 Redux Chat

Angular 2 Redux Chat Join the chat at https://gitter.im/ng-book/ng-book

An Angular 2 chat app using Angular 2, Redux, Webpack, TypeScript, Services, Injectables, Karma, Forms, SCSS, and tslint by the ng-book 2 team

This repo shows an example chat application using Redux and Angular 2. The goal is to show how to use the Redux data architecture pattern within Angular 2, using the core Redux library. It also features:

Try the live demo here

Angular 2 Redux Chat

Quick start

# clone the repo
git clone https://github.com/ng-book/angular2-redux-chat.git 

# change into the repo directory
cd angular2-redux-chat

# install 
npm install

# run
npm run go

Then visit http://localhost:8080 in your browser.

Architecture

The app has three models:

  • Message - holds individual chat messages
  • Thread - holds metadata for a group of Messages
  • User - holds data about an individual user

Model Diagram

There are two reducers:

There are also three top-level components:

  • ChatNavBar - for the top navigation bar and unread messages count
  • ChatThreads - for our clickable list of threads
  • ChatWindow - where we hold our current conversation

Angular 2 Redux Chat

Components Subscribe to the Store

In this project, we're using the official Redux library instead of a wrapper or Redux-inspired spin-off. At the top of our app we create a new Redux Store and provide it to the dependency injection system. This let's us inject it into our components.

Our container components inject the Redux Store and subscribe to any changes. Consider this excerpt from the nav-bar which keeps the count of unread messages:

export default class ChatNavBar  {
  unreadMessagesCount: number;

  constructor(@Inject(AppStore) private store: Store<AppState>) {
    store.subscribe(() => this.updateState());
    this.updateState();
  }

  updateState() {
    // getUnreadMessagesCount is a selector function
    this.unreadMessagesCount = getUnreadMessagesCount(this.store.getState());
  }
}

You can see that in the constructor we inject our Store (which is typed to AppState). We immediately subscribe to any changes in the store. This callback will not be called unless an action is dispatched to the store, so we need to make sure we load the initial data. To do this, we call this.updateState() one time after the subscription.

updateState reads the state from the store (this.store.getState()) and then calls the selector function getUnreadMessagesCount (you can find the implementation of that here). getUnreadMessagesCount calculates the number of unread messages. We then take that value and set it to this.unreadMessagesCount. Because unreadMessagesCount is an instance variable which appears in the template, Angular will rerender this component when the value changes.

This pattern is used throughout the app.

Understanding how everything fits together with Redux can be tricky, but this code is heavily commented. One strategy to understand this code is to start at the components and see how they read the Store with selectors, dispatch actions, and follow that through the reducers. The other strategy is to get a copy of ng-book 2 where we explain each line in detail over ~60 pages.

State

The top-level state has two keys: users and threads:

interface AppState {
  users: UsersState;
  threads: ThreadsState;
}

interface UsersState {
  currentUser: User;
};

export interface ThreadsEntities {
  [id: string]: Thread;
}

export interface ThreadsState {
  ids: string[];
  entities: ThreadsEntities;
  currentThreadId?: string;
};

ThreadsState stores the list of Threads indexed by id in entities, as well as a complete list of the ids in ids.

We also store the id of the current thread so that we know what the user is currently looking at - this is valuable for the unread messages count, for instance.

In this app, we store the Messages in their respective Thread and we don't store the Messages apart from that Thread. In your app you may find it useful to separate Messages into their own Messages reducer and keep only a list of Message ids in your Threads.

Here's a screenshot using Redux Devtools of the initial state:

Angular 2 Redux Chat State Tree

Bots

This app implements a few simple chat bots. For instance:

  • Echo bot
  • Reversing bot
  • Waiting bot

Angular 2 Redux Chat Bots

File Structure

Here's an overview of how the files are laid out in this project:

angular2-redux-chat
├── Makefile                        * Easy access to common tasks
├── README.md                       * This file
├── app/                            * Where our application code is stored
│   ├── css/                        * Contains our CSS and SCSS files
|   | 
│   ├── images/                     * App Images
|   | 
│   ├── index.html                  * HTML entry point
|   | 
│   └── ts/                         * All of our TypeScript is here
│       │
│       ├── ChatExampleData.ts      * Contains our bots and sample data
|       |
│       ├── actions/                * Our Redux actions
│       │   ├── ThreadActions.ts    * Actions for Threads
│       │   ├── UserActions.ts      * Actions for Users
│       │   └── index.ts            
|       |
│       ├── app-store.ts            * A token for DI of the Store
│       ├── app.ts                  * App entry point
|       |
│       ├── components/             * Pure Components go here
│       │   ├── ChatMessage.ts      * Shows a single Message
│       │   └── ChatThread.ts       * Shows a single Thread
|       |
│       ├── containers/             * Containers that access the Store here
│       │   ├── ChatNavBar.ts       * The nav bar
│       │   ├── ChatThreads.ts      * The list of threads
│       │   └── ChatWindow.ts       * The window where we chat
|       |
│       ├── models/                 * Models here
│       │   ├── Message.ts          * Message model
│       │   ├── Thread.ts           * Thread model
│       │   ├── User.ts             * User model
│       │   └── index.ts
|       |
│       ├── pages/                  * Pages of the app here
│       │   └── ChatPage.ts         * The main chat page
|       |
│       ├── pipes/                  * Our pipes here
│       │   └── FromNowPipe.ts      * 'n minutes ago' pipe
|       |
│       ├── reducers/               * Redux reducers
│       │   ├── ThreadsReducer.ts   * Manages thread state
│       │   ├── UsersReducer.ts     * Manages users state
│       │   └── index.ts
|       |
│       ├── util/                   * Utility functions
│       │   └── uuid.ts
│       └── vendor.ts               * Dependencies loaded here
| 
├── karma.conf.js                   * Test configuration
| 
├── minimal/                        * A minimal counter app w/ Redux/ng2
│   ├── CounterComponent.ts
│   ├── app-state.ts
│   ├── app-store.ts
│   ├── app.ts
│   ├── counter-action-creators.ts
│   ├── counter-reducer.ts
│   ├── index.html
│   └── tutorial/                   * Tutorial to build a store
│       ├── 01-identity-reducer.ts
│       ├── 02-adjusting-reducer.ts
│       ├── 03-adjusting-reducer-switch.ts
│       ├── 04-plus-action.ts
│       ├── 05-minimal-store.ts
│       ├── 06-rx-store.ts
│       ├── redux2.ts
│       └── tsconfig.json
├── package.json                    * npm dependencies
├── test/                           * tests go here
├── test.bundle.js                  * webpack test loader
├── tsconfig.json                   * compiler configuration
├── tslint.json                     * code standards configuration
├── typings/                        * TypeScript typings definitions
├── typings.json                    * typings configuration
└── webpack.config.js               * Webpack configuration

Detailed Installation

Step 1: Install Node.js from the Node Website.

We recommend Node version 4.1 or above. You can check your node version by running this:

$ node -v
vv4.1...

Step 2: Install Dependencies

npm install

Running the App

npm run go

Then visit http://localhost:8080 in your browser.

Running the Tests

You can run the unit tests with:

npm run test

Build Redux in TypeScript Tutorial

This repository contains a step-by-step tutorial on how to build a minimal-redux store in Typescript. You can read a blog post explaining this code here. You can also find the code in minimal/tutorial. The final result looks like this (with or without Observables):

Minimal Redux in TypeScript

Minimal Angular 2 Redux Integration

This repository also contains an example of a minimal integration of Redux with Angular 2 to build a counter app. You can also read about how to build this project here at the ng-book blog.

Minimal Redux and Angular 2 Counter

Series

This repo is part of a series of projects that discuss data architecture with Angular 2. You can find this same project implemented with Observable streams instead of Redux here:

Contributing

There are lots of other little things that need cleaned up such as:

  • More tests
  • Cleaning up the vendor scripts / typings

If you'd like to contribute, feel free to submit a pull request and we'll likely merge it in.

Getting Help

If you're having trouble getting this project running, feel free to open an issue, join us on Gitter, or email us!


ng-book 2

ng-book 2

This repo was written and is maintained by the ng-book 2 team. In the book we talk about each line of code in this app and explain why it's there and how it works.

This app is only one of several apps we have in the book. If you're looking to learn Angular 2, there's no faster way than by spending a few hours with ng-book 2.

License

MIT

angular2-redux-chat's People

Contributors

daynedavis avatar gitter-badger avatar jashmenn avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.