-
-
Save JamesHenry/d93766a07c516361fa75a376273590d4 to your computer and use it in GitHub Desktop.
ngMetadata 2.x - with @ngrx/store
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from 'ng-metadata/core' | |
import { Action } from '@ngrx/store' | |
interface SomePayload { | |
baz: string | |
} | |
/** | |
* Instead of passing around action string constants and manually recreating | |
* action objects at the point of dispatch, we create services encapsulating | |
* each appropriate action group. Action types are included as static | |
* members and kept next to their action creator. This promotes a | |
* uniform interface and single import for appropriate actions | |
* within your application components. | |
*/ | |
@Injectable() | |
export class FooActions { | |
static BAR = 'Bar' | |
bar(somePayload: SomePayload): Action { | |
return { | |
type: FooActions.BAR, | |
payload: somePayload, | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { FooActions } from './foo' | |
export { | |
FooActions, | |
} | |
export default [ | |
FooActions, | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from 'ng-metadata/core'; | |
import { FooComponent } from './foo.component' | |
@Component({ | |
selector: 'my-app', | |
template: ` | |
<h1>My First Angular 1 App <small>with ng-metadata!</small></h1> | |
<br><br> | |
<foo></foo> | |
`, | |
directives: [FooComponent], | |
}) | |
export class AppComponent { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from 'ng-metadata/core' | |
import { Store } from './ngrx-store-one' | |
import { FooState } from './reducers/foo' | |
import { FooActions } from './actions/index' | |
@Component({ | |
selector: 'foo', | |
template: ` | |
<p>Foo.qux state:</p> | |
<h3 style="color: blue;">{{ ($ctrl.foo | async:this).qux }}</h3> | |
<button ng-click="$ctrl.onClick()">Click me!</button> | |
`, | |
}) | |
export class FooComponent { | |
foo: Observable<number> | |
constructor( | |
private store: Store<AppState>, | |
private fooActions: FooActions | |
) { | |
this.foo = this.store.select<FooState>('foo') | |
} | |
onClick() { | |
this.store.dispatch(this.fooActions.bar({ | |
baz: Math.random().toString(16).slice(2), | |
})) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export { AppComponent } from './app.component'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { bootstrap } from 'ng-metadata/platform-browser-dynamic'; | |
import { AsyncPipe } from 'ng-metadata/common' | |
import { provideStore } from './ngrx-store-one' | |
import reducers from './reducers/index' | |
import actions from './actions/index' | |
import { AppComponent } from './index'; | |
const providers = [ | |
AsyncPipe, | |
provideStore(reducers), | |
actions, | |
] | |
/** | |
* Bootstrap the Angular application using ng-metadata, | |
* which uses strict dependency injection by default | |
*/ | |
bootstrap(AppComponent, providers) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Import @ngrx/store providers | |
*/ | |
import { Reducer } from '@ngrx/store' | |
import { Dispatcher } from '@ngrx/store' | |
import { Store } from '@ngrx/store' | |
import { State } from '@ngrx/store' | |
import { combineReducers } from '@ngrx/store' | |
/** | |
* Create annotated versions of the providers so that ng-metadata | |
* can register them against our ng1 app | |
*/ | |
import { Injectable, OpaqueToken } from 'ng-metadata/core' | |
@Injectable() | |
class Ng1Dispatcher extends Dispatcher {} | |
@Injectable() | |
class Ng1Store<T> extends Store<T> {} | |
@Injectable() | |
class Ng1State<T> extends State<T> {} | |
@Injectable() | |
class Ng1Reducer extends Reducer {} | |
/** | |
* ng-metadata doesn't currently support objects created via `new String()`, | |
* so create an alternative INITIAL_REDUCER and INITIAL_STATE using OpaqueToken | |
*/ | |
export const INITIAL_REDUCER = new OpaqueToken('Token ngrx/store/reducer') | |
export const INITIAL_STATE = new OpaqueToken('Token ngrx/store/initial-state') | |
/** | |
* Replicate the structure of the contents of ng2.ts from @ngrx/store, | |
* but using the annotated dependencies | |
*/ | |
const dispatcherProvider = { | |
provide: Ng1Dispatcher, | |
useFactory() { | |
return new Dispatcher() | |
} | |
} | |
const storeProvider = { | |
provide: Ng1Store, | |
deps: [Ng1Dispatcher, Ng1Reducer, Ng1State, INITIAL_STATE], | |
useFactory(dispatcher: Dispatcher, reducer: Reducer, state$: State<any>, initialState: any) { | |
return new Store<any>(dispatcher, reducer, state$, initialState) | |
} | |
} | |
const stateProvider = { | |
provide: Ng1State, | |
deps: [INITIAL_STATE, Ng1Dispatcher, Ng1Reducer], | |
useFactory(initialState: any, dispatcher: Dispatcher, reducer: Reducer) { | |
return new State(initialState, dispatcher, reducer) | |
} | |
} | |
const reducerProvider = { | |
provide: Ng1Reducer, | |
deps: [Ng1Dispatcher, INITIAL_REDUCER], | |
useFactory(dispatcher: Dispatcher, reducer: any) { | |
return new Reducer(dispatcher, reducer) | |
} | |
} | |
export function provideStore(reducer: any, initialState?: any): any[] { | |
return [ | |
{ | |
provide: INITIAL_REDUCER, | |
useFactory() { | |
if (typeof reducer === 'function') { | |
return reducer | |
} | |
return combineReducers(reducer) | |
} | |
}, | |
{ | |
provide: INITIAL_STATE, | |
deps: [INITIAL_REDUCER], | |
useFactory(reducer: Function) { | |
if (initialState === undefined) { | |
return reducer(undefined, { type: Dispatcher.INIT }) | |
} | |
return initialState | |
} | |
}, | |
dispatcherProvider, | |
storeProvider, | |
stateProvider, | |
reducerProvider, | |
] | |
} | |
/** | |
* Export the annotated store as `Store` so that we match | |
* the public interface of @ngrx/store | |
*/ | |
export { Ng1Store as Store } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Action, ActionReducer } from '@ngrx/store' | |
import { FooActions } from '../actions/index' | |
export interface FooState { | |
qux: string | |
} | |
const initialState: FooState = { | |
qux: 'No one has clicked me :(', | |
} | |
const fooReducer: ActionReducer<FooState> = (state = initialState, action: Action) => { | |
switch (action.type) { | |
case FooActions.BAR: | |
return Object.assign({}, state, { | |
qux: action.payload.baz, | |
}) | |
default: | |
return state | |
} | |
} | |
export default fooReducer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The compose function is one of our most handy tools. In basic terms, you give | |
* it any number of functions and it returns a function. This new function | |
* takes a value and chains it through every composed function, returning | |
* the output. | |
* | |
* More: https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch5.html | |
*/ | |
import { compose } from '@ngrx/core/compose' | |
/** | |
* storeLogger is a powerful metareducer that logs out each time we dispatch | |
* an action. | |
* | |
* A metareducer wraps a reducer function and returns a new reducer function | |
* with superpowers. They are handy for all sorts of tasks, including | |
* logging, undo/redo, and more. | |
*/ | |
import { storeLogger } from 'ngrx-store-logger' | |
/** | |
* combineReducers is another useful metareducer that takes a map of reducer | |
* functions and creates a new reducer that stores the gathers the values | |
* of each reducer and stores them using the reducer's key. Think of it | |
* almost like a database, where every reducer is a table in the db. | |
* | |
* More: https://egghead.io/lessons/javascript-redux-implementing-combinereducers-from-scratch | |
*/ | |
import { combineReducers } from '@ngrx/store' | |
/** | |
* Import reducers and state interfaces | |
*/ | |
import fooReducer, { FooState } from './foo' | |
/** | |
* We treat each reducer like a table in a database. This means | |
* our top level state interface is just a map of keys to inner state types. | |
*/ | |
export interface AppState { | |
foo: FooState | |
} | |
/** | |
* Because metareducers take a reducer function and return a new reducer, | |
* we can use our compose helper to chain them together. Here we are | |
* using combineReducers to make our top level reducer, and then | |
* wrapping that in storeLogger. Remember that compose applies | |
* the result from right to left. | |
*/ | |
export default compose(storeLogger(), combineReducers)({ | |
foo: fooReducer, | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<!-- 1. Load libraries --> | |
<!-- Polyfill(s) for older browsers --> | |
<script src="https://npmcdn.com/core-js/client/shim.min.js"></script> | |
<script src="https://npmcdn.com/reflect-metadata@0.1.3"></script> | |
<script src="https://npmcdn.com/systemjs@0.19.27/dist/system.src.js"></script> | |
<script src="https://code.angularjs.org/1.5.7/angular.js"></script> | |
<!-- 2. Configure SystemJS --> | |
<script src="systemjs.config.js"></script> | |
<script> | |
System.import('app').catch(function(err){ console.error(err); }); | |
</script> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<!-- 3. Display the application --> | |
<body> | |
<my-app>Loading...</my-app> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
console.log('Hello World!'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* todo: add styles */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
System.config({ | |
//use typescript for compilation | |
transpiler: 'ts', | |
typescriptOptions: { | |
tsconfig: true | |
}, | |
meta: { | |
'typescript': { | |
"exports": "ts" | |
} | |
}, | |
//map tells the System loader where to look for things | |
map: { | |
'app': './app', | |
'ng-metadata': 'https://npmcdn.com/ng-metadata', | |
'ngrx-store-logger': 'https://npmcdn.com/ngrx-store-logger', | |
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6', | |
'@ngrx/store': 'https://npmcdn.com/@ngrx/store', | |
'@ngrx/core': 'https://npmcdn.com/@ngrx/core', | |
'ts': 'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js', | |
'typescript': 'https://npmcdn.com/typescript@1.9.0-dev.20160409/lib/typescript.js', | |
}, | |
//packages defines our app package | |
packages: { | |
app: { | |
main: './main.ts', | |
defaultExtension: 'ts' | |
}, | |
'ng-metadata': { | |
defaultExtension: 'js' | |
}, | |
'ngrx-store-logger': { | |
defaultExtension: 'js' | |
}, | |
'rxjs': { | |
main: 'index.js', | |
defaultExtension: 'js' | |
}, | |
'@ngrx/core': { | |
main: 'index.js', | |
format: 'cjs' | |
}, | |
'@ngrx/store': { | |
main: 'index.js', | |
format: 'cjs' | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"compilerOptions": { | |
"target": "es5", | |
"module": "commonjs", | |
"moduleResolution": "node", | |
"sourceMap": true, | |
"emitDecoratorMetadata": true, | |
"experimentalDecorators": true, | |
"removeComments": false, | |
"noImplicitAny": true, | |
"suppressImplicitAnyIndexErrors": true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment