diff --git a/.gitignore b/.gitignore index e849ca7..66a78bd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ lib coverage *.tgz examples/**/dist +.envrc +.nvmrc diff --git a/README.md b/README.md index 7fff021..fb41265 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ Add the following script tag to your html: #### Initialization +You can initialize ngRedux two ways: + +Function as the reducer argument for the `createStoreWith`: + ```JS import reducers from './reducers'; import { combineReducers } from 'redux'; @@ -54,6 +58,49 @@ angular.module('app', [ngRedux]) }); ``` +A reducer object as reducer argument for the `createStoreWith`: + +```JS +import reducers from './reducers'; +import { combineReducers } from 'redux'; +import loggingMiddleware from './loggingMiddleware'; +import ngRedux from 'ng-redux'; + +angular.module('app', [ngRedux]) +.config(($ngReduxProvider) => { + reducer3 = function(state, action){} + $ngReduxProvider.createStoreWith({ + reducer1: "reducer1", + reducer2: function(state, action){}, + reducer3: reducer3 + }, ['promiseMiddleware', loggingMiddleware]); + }); +``` + +The object can be constructed either by passing a function as value or a string representing the reducer. This way, you can create reducers as services and initialze them inside the `.config`. Behind the secnes, ngRedux will `$injector.get` the string you pass as the value for the ojects of reducers and initilaze it. + +You can also pass custom `combineReducers` to `$ngReduxProvider`, which is extremely helpfull if you want to use libraries such as [redux-immutable](https://github.com/gajus/redux-immutable) for example. + +```JS +import reducers from './reducers'; +import myCombineReducers from 'redux-immutable'; +import loggingMiddleware from './loggingMiddleware'; +import ngRedux from 'ng-redux'; + +angular.module('app', [ngRedux]) +.config(($ngReduxProvider) => { + $ngReduxProvider.setCombineReducersFunc(myCombineReducers); + reducer3 = function(state, action){} + $ngReduxProvider.createStoreWith({ + reducer1: "reducer1", + reducer2: function(state, action){}, + reducer3: reducer3 + }, ['promiseMiddleware', loggingMiddleware]); + }); +``` + +By passing `$ngReduxProvider.setCombineReducersFunc(myCombineReducers);`, ngRedux will use the new myCombineReducers function instead of the default one that comes with redux. + #### Usage *Using controllerAs syntax* diff --git a/package.json b/package.json index 8a75f91..7dbc774 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "ng-redux", + "version": "3.3.5-beta.0", "description": "Redux bindings for Angular.js", "main": "./lib/index.js", "scripts": { diff --git a/src/components/ngRedux.js b/src/components/ngRedux.js index 314a9c0..2682351 100644 --- a/src/components/ngRedux.js +++ b/src/components/ngRedux.js @@ -1,22 +1,35 @@ import Connector from './connector'; import invariant from 'invariant'; -import {createStore, applyMiddleware, compose} from 'redux'; +import {createStore, applyMiddleware, compose, combineReducers} from 'redux'; import digestMiddleware from './digestMiddleware'; import assign from 'lodash.assign'; import isArray from 'lodash.isarray'; import isFunction from 'lodash.isfunction'; +import isObject from 'lodash.isobject'; export default function ngReduxProvider() { let _reducer = undefined; let _middlewares = undefined; let _storeEnhancers = undefined; let _initialState = undefined; + let _reducerIsObject = undefined; + let _combineReducers = undefined; + + this.setCombineReducersFunc = (func) => { + invariant( + isFunction(func), + 'The parameter passed to setCombineReducersFunc must be a Function. Instead received %s.', + typeof func + ); + + _combineReducers = func; + }; this.createStoreWith = (reducer, middlewares, storeEnhancers, initialState) => { invariant( - isFunction(reducer), - 'The reducer parameter passed to createStoreWith must be a Function. Instead received %s.', + isFunction(reducer) || isObject(reducer), + 'The reducer parameter passed to createStoreWith must be a Function or an Object. Instead received %s.', typeof reducer ); @@ -27,6 +40,7 @@ export default function ngReduxProvider() { ); _reducer = reducer; + _reducerIsObject = isObject(reducer); _storeEnhancers = storeEnhancers _middlewares = middlewares || []; _initialState = initialState; @@ -34,6 +48,7 @@ export default function ngReduxProvider() { this.$get = ($injector) => { let store, resolvedMiddleware = []; + let finalCombineReducers = _combineReducers ? _combineReducers : combineReducers; for(let middleware of _middlewares) { if(typeof middleware === 'string') { @@ -43,12 +58,27 @@ export default function ngReduxProvider() { } } + if(_reducerIsObject) { + let reducersObj = {}; + let reducKeys = Object.keys(_reducer); + + reducKeys.forEach((key) => { + if(typeof _reducer[key] === 'string') { + reducersObj[key] = $injector.get(_reducer[key]); + } else { + reducersObj[key] = _reducer[key]; + } + }); + + _reducer = finalCombineReducers(reducersObj); + } + let finalCreateStore = _storeEnhancers ? compose(..._storeEnhancers)(createStore) : createStore; //digestMiddleware needs to be the last one. resolvedMiddleware.push(digestMiddleware($injector.get('$rootScope'))); - store = _initialState + store = _initialState ? applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer, _initialState) : applyMiddleware(...resolvedMiddleware)(finalCreateStore)(_reducer);