Skip to content

Instantly share code, notes, and snippets.

@johnlindquist
Last active March 18, 2016 01:23
Show Gist options
  • Save johnlindquist/46b6835ad29f59fed54e to your computer and use it in GitHub Desktop.
Save johnlindquist/46b6835ad29f59fed54e to your computer and use it in GitHub Desktop.
Angular2 + store-saga Todos

Angular2 Starter Plunker - Typescript - Beta 10

A todo example with @ngrx/store and store-saga

System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
//map tells the System loader where to look for things
map: {
app: "./src",
'@ngrx': 'https://npmcdn.com/@ngrx',
'store-saga': 'https://npmcdn.com/[email protected]',
'rxjs': 'https://npmcdn.com/rxjs'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
'@ngrx/store': {
main: 'dist/index.js',
defaultExtension: 'js'
},
'@ngrx/devtools': {
main: 'dist/index.js',
defaultExtension: 'js'
},
'store-saga': {
main: 'index.js',
defaultExtension: 'js'
},
'rxjs': {
main: 'index.js',
defaultExtension: 'js'
}
}
});
<!DOCTYPE html>
<html>
<head>
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/2.0.0-beta.10/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="config.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.10/angular2.dev.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.10/http.dev.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
//our root app component
import {Component} from 'angular2/core'
import {Observable} from 'rxjs/Rx'
import {Store, provideStore} from '@ngrx/store'
import {instrumentStore, Devtools} from '@ngrx/devtools'
import {installSagaMiddleware} from 'store-saga';
import todoEffects from './sagas';
import {todos} from './todos'
@Component({
selector: 'my-app',
template: `
<ngrx-devtools></ngrx-devtools>
<h2>Todos</h2>
<input #newtodo type="text"/>
<button (click)="addTodo(newtodo)">add</button>
<ul>
<li *ngFor="#todo of todos | async" [class.completed]="todo.completed">
{{todo.text}}
</li>
</ul>
`,
styles: [`
.completed {
text-decoration: line-through;
}
`],
providers: [
provideStore({todos}),
instrumentStore(),
installSagaMiddleware(...todoEffects)
],
directives: [Devtools]
})
export class TodoApp {
todos: Observable<any[]>
constructor(private store:Store<any>){
this.todos = store.select('todos');
}
addTodo(el){
this.store.dispatch({type: 'ADD_TODO', payload: {
text: el.value
}});
el.value = ''
}
}
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {TodoApp} from './app';
bootstrap(TodoApp)
.catch(err => console.error(err));
import 'rxjs/add/operator/delay';
import { createSaga, whenAction } from 'store-saga';
import { ADD_TODO, COMPLETE_TODO } from './todos';
export const markAsComplete = createSaga(function() {
return saga$ => saga$
.filter(whenAction(ADD_TODO))
.map(({ state }) => {
const { todos } = state;
const last = todos[todos.length - 1];
return {
type: COMPLETE_TODO,
payload: {
id: last.id
}
};
})
.delay(1);
});
export default [ markAsComplete ];
//todos reducer
export const ADD_TODO = 'ADD_TODO';
export const UPDATE_TODO = 'UPDATE_TODO';
export const DELETE_TODO = 'DELETE_TODO';
export const COMPLETE_TODO = 'COMPLETE_TODO';
export const todos = (state = [], {type, payload}) => {
switch(type){
case ADD_TODO:
return state.concat([Object.assign({}, payload, {id: state.length + 1})]);
case UPDATE_TODO:
return state.map(todo => {
return todo.id !== payload.id ?
todo :
Object.assign({}, todo, payload)
});
case COMPLETE_TODO:
return state.map(todo => {
return todo.id !== payload.id ?
todo :
Object.assign({}, todo, {completed: true})
});
case DELETE_TODO:
return state.filter(todo => todo.id !== payload.id);
default:
return state;
}
}
/* Styles go here */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment