diff --git a/README.md b/README.md
index 88c404a..1e1e1c4 100644
--- a/README.md
+++ b/README.md
@@ -3,56 +3,36 @@
For Angular 2 see [ng2-redux](https://github.com/wbuchwalter/ng2-redux).
-**Warning: The API will be subject to breaking changes until `1.0.0` is released. You can follow progress on the `bc-1.0.0` branch**
+**Warning: The API will be subject to breaking changes until `1.0.0` is released.**
[](https://travis-ci.org/wbuchwalter/ng-redux)
[](https://www.npmjs.com/package/ng-redux)
-## Installation
-```js
-npm install --save ng-redux
-```
-## Overview
+*ngRedux lets you easily connect your angular components with Redux.*
-ngRedux lets you easily connect your angular components with Redux.
-the API is straightforward:
-```JS
-$ngRedux.connect(selector, callback);
-```
+## Table of Contents
-Where `selector` is a function that takes Redux's entire store state as argument and returns an object that contains the slices of store state that your component is interested in.
-e.g:
-```JS
-state => ({todos: state.todos})
-```
-Note: if you are not familiar with this syntax, go and check out the [MDN Guide on fat arrow functions (ES2015)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
-
-If you haven't, check out [reselect](https://github.com/faassen/reselect), an awesome tool to create and combine selectors.
+- [Installation](#installation)
+- [Quick Start](#quick-start)
+- [API](#api)
+- [Using DevTools](#using-devtools)
+## Installation
-This returned object will be passed as argument to the callback provided whenever the state changes.
-ngRedux checks for shallow equality of the state's selected slice whenever the Store is updated, and will call the callback only if there is a change.
-**Important: It is assumed that you never mutate your states, if you do mutate them, ng-redux will not execute the callback properly.**
-See [Redux's doc](http://gaearon.github.io/redux/docs/basics/Reducers.html) to understand why you should not mutate your states.
-
+**The current npm version is outdated, and will be updated once 1.0.0 is finished**
+```js
+npm install --save ng-redux
+```
-## Getting Started
+## Quick Start
#### Initialization
-```JS
-$ngReduxProvider.createStoreWith(reducer, [middlewares], storeEnhancer);
-```
-#### Parameters:
-* reducer (Function): A single reducer composed of all other reducers (create with redux.combineReducer)
-* [middleware] (Array of Function or String): An array containing all the middleware that should be applied. Functions and strings are both valid members. String will be resolved via Angular, allowing you to use dependency injection in your middlewares.
-* storeEnhancer: Optional function that will be used to create the store, in most cases you don't need that, see [Store Enhancer official doc](http://rackt.github.io/redux/docs/Glossary.html#store-enhancer)
-
```JS
import reducers from './reducers';
-import {combineReducers} from 'redux';
+import { combineReducers } from 'redux';
import loggingMiddleware from './loggingMiddleware';
import 'ng-redux';
@@ -64,75 +44,120 @@ angular.module('app', ['ngRedux'])
```
#### Usage
-```JS
- export default function todoLoader() {
- return {
- controllerAs: 'vm',
- controller: TodoLoaderController,
- template: "
{{todo.text}}
",
-
- [...]
- };
-}
+*Note: this sample is using the ControllerAs syntax, usage is slightly different without ControllerAs, see API section for more details*
-class TodoLoaderController {
-
- constructor($ngRedux) {
- this.todos = [];
- $ngRedux.connect(state => ({todos: state.todos}), ({todos}) => this.todos = todos);
+```JS
+import * as CounterActions from '../actions/counter';
+
+class CounterController {
+ constructor($ngRedux, $scope) {
+ /* ngRedux will merge the requested state's slice and actions onto the $scope,
+ you don't need to redefine them in your controller */
+
+ $ngRedux.connect($scope, this.mapStateToScope, CounterActions, 'vm');
}
- [...]
+ // Which part of the Redux global state does our component want to receive on $scope?
+ mapStateToScope(state) {
+ return {
+ counter: state.counter
+ };
+ }
}
```
-**Note: The callback provided to `connect` will be called once directly after creation to allow initialization of your component states**
+```HTML
+
+
Clicked: {{vm.counter}} times
+
+
+
+
+
+```
+## API
+### `createStoreWith([reducer], [middlewares], [storeEnhancers])`
-You can also grab multiple slices of the state by passing an array of selectors:
+Creates the Redux store, and allow `connect()` to access it.
-```JS
-constructor($ngRedux) {
- this.todos = [];
- this.users = [];
- $ngRedux.connect(state => ({
- todos: state.todos,
- users: state.users
- }),
- ({todos, users}) => {
- this.todos = todos
- this.users = users;
- });
- }
-```
+#### Arguments:
+* [`reducer`] \(*Function*): A single reducer composed of all other reducers (create with redux.combineReducer)
+* [`middlewares`] \(*Function[]*): Optional, An array containing all the middleware that should be applied. Functions and strings are both valid members. String will be resolved via Angular, allowing you to use dependency injection in your middlewares.
+* [`storeEnhancers`] \(*Function[]*): Optional, this will be used to create the store, in most cases you don't need to pass anything, see [Store Enhancer official documentation.](http://rackt.github.io/redux/docs/Glossary.html#store-enhancer)
-#### Unsubscribing
+### `connect([scope], [mapStateToScope], [mapDispatchToScope], [propertyKey])`
-You can close a connection like this:
+Connects an Angular component to Redux.
-```JS
+#### Arguments
+* [`scope`] \(*Object*): The `$scope` of your controller.
+* [`mapStateToScope`] \(*Function*): connect will subscribe to Redux store updates. Any time it updates, mapStateToTarget will be called. Its result must be a plain object, and it will be merged into `target`.
+* [`mapDispatchToScope`] \(*Object* or *Function*): If an object is passed, each function inside it will be assumed to be a Redux action creator. An object with the same function names, but bound to a Redux store, will be merged into your component `$scope`. If a function is passed, it will be given `dispatch`. It’s up to you to return an object that somehow uses `dispatch` to bind action creators in your own way. (Tip: you may use the [`bindActionCreators()`](http://gaearon.github.io/redux/docs/api/bindActionCreators.html) helper from Redux.).
+* [`propertyKey`] \(*string*): If provided, `mapStateToScope` and `mapDispatchToScope` will merge onto `$scope[propertyKey]`. This is needed especially when using the `ControllerAs` syntax: in this case you should provide the same value than the value provided to controllerAs (e.g: `'vm'`). When not using `ControllerAs` syntax, you are free to omit this argument, everything will be merged directly onto `$scope`.
-constructor($ngRedux) {
- this.todos = [];
- this.unsubscribe = $ngRedux.connect(state => ({todos: state.todos}), ({todos}) => this.todos = todos);
- }
+#### Remarks
+As `$scope` is passed to `connect`, ngRedux will listen to the `$destroy` event and unsubscribe the change listener itself, you don't need to keep track of your subscribtions.
-destroy() {
- this.unsubscribe();
-}
+### Store API
+All of redux's store methods (i.e. `dispatch`, `subscribe` and `getState`) are exposed by $ngRedux and can be accessed directly. For example:
+```JS
+$ngRedux.subscribe(() => {
+ let state = $ngRedux.getState();
+ //...
+})
```
+This means that you are free to use Redux basic API in advanced cases where `connect`'s API would not fill your needs.
-#### Accessing Redux's store methods
-All of redux's store methods (i.e. `dispatch`, `subscribe` and `getState`) are exposed by $ngRedux and can be accessed directly. For example:
+
+## Using DevTools
+In order to use Redux DevTools with your angular app, you need to install [react](https://www.npmjs.com/package/react), [react-redux](https://www.npmjs.com/package/react-redux) and [redux-devtools](https://www.npmjs.com/package/redux-devtools) as development dependencies.
```JS
-redux.bindActionCreators(actionCreator, $ngRedux.dispatch);
+[...]
+import { devTools, persistState } from 'redux-devtools';
+import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
+import React, { Component } from 'react';
+
+angular.module('app', ['ngRedux'])
+ .config(($ngReduxProvider) => {
+ $ngReduxProvider.createStoreWith(rootReducer, [thunk], [devTools()]);
+ })
+ .run(($ngRedux, $rootScope) => {
+ React.render(
+ ,
+ document.getElementById('devTools')
+ );
+
+ //To reflect state changes when disabling/enabling actions via the monitor
+ //there is probably a smarter way to achieve that
+ $ngRedux.subscribe(_ => {
+ setTimeout($rootScope.$apply, 100);
+ });
+ });
+
+ class App extends Component {
+ render() {
+ return (
+
+
+
+
+
+ );
+ }
+}
```
-**Note:** If you choose to use `subscribe` directly, be sure to [unsubscribe](#unsubscribing) when your current scope is $destroyed.
-### Example:
-An example can be found here (in TypeScript): [tsRedux](https://github.com/wbuchwalter/tsRedux/blob/master/src/components/regionLister.ts).
+```HTML
+
+
+ [...]
+
+
+
+```
diff --git a/examples/counter/components/counter.html b/examples/counter/components/counter.html
index 71de309..7912361 100644
--- a/examples/counter/components/counter.html
+++ b/examples/counter/components/counter.html
@@ -4,4 +4,5 @@
+
diff --git a/examples/counter/components/counter.js b/examples/counter/components/counter.js
index e5e0028..1e9e4f3 100644
--- a/examples/counter/components/counter.js
+++ b/examples/counter/components/counter.js
@@ -13,16 +13,14 @@ export default function counter() {
class CounterController {
- constructor($ngRedux) {
- this.counter = 0;
- $ngRedux.connect(state => ({
- counter: state.counter
- }),
- ({counter}) => this.counter = counter);
+ constructor($ngRedux, $scope) {
+ $ngRedux.connect($scope, this.mapStateToScope, CounterActions, 'vm');
+ }
- let {increment, decrement, incrementIfOdd} = bindActionCreators(CounterActions, $ngRedux.dispatch);
- this.increment = increment;
- this.decrement = decrement;
- this.incrementIfOdd = incrementIfOdd;
+ // Which part of the Redux global state does our component want to receive on $scope?
+ mapStateToScope(state) {
+ return {
+ counter: state.counter
+ };
}
}
\ No newline at end of file
diff --git a/examples/counter/devTools.js b/examples/counter/devTools.js
new file mode 100644
index 0000000..892a090
--- /dev/null
+++ b/examples/counter/devTools.js
@@ -0,0 +1,30 @@
+import { persistState } from 'redux-devtools';
+import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
+import React, { Component } from 'react';
+
+angular.module('counter')
+ .run(($ngRedux, $rootScope) => {
+ React.render(
+ ,
+ document.getElementById('devTools')
+ );
+ //Hack to reflect state changes when disabling/enabling actions via the monitor
+ $ngRedux.subscribe(_ => {
+ setTimeout($rootScope.$apply, 100);
+ });
+ });
+
+
+class App extends Component {
+ render() {
+ return (
+