by Gerard Sans | @gerardsans
Spoken at 92 events in 25 countries
900
1.5K
Components
Actions
State
Mutate
Dispatch
Notify
actions
states
A
A
A
S
S
S
Components
Actions
State
Mutate
Dispatch
Notify
Plugins
Actions
State
Increment
Decrement
Reset
Total
Components
Actions
State
Mutate
Dispatch
Notify
import { State } from '@ngxs/store';
@State<number>({
name: 'counter',
defaults: 0
})
export class CounterState { }
src/app.component.ts
app/store/counter.state.ts
Components
Actions
State
Mutate
Dispatch
Notify
export class Increment {
static readonly type = "[Counter] Increment";
}
// const action = new Increment();
// {
// type: "[Counter] Increment"
// }
src/app.component.ts
app/store/counter.actions.ts
import { State, Action, StateContext } from '@ngxs/store';
import { Increment } from '../store/counter.actions';
@State<number>({ name: 'counter', defaults: 0 })
export class CounterState {
@Action(Increment)
Increment(store: StateContext<number>) {
const counter = store.getState();
store.setState(counter+1);
}
}
src/app.component.ts
app/store/counter.state.ts
export class Reset {
static readonly type = "[Counter] Reset";
constructor(public payload: { value: number }) { }
}
// const action = new Reset({ value: 0 });
// {
// type: "[Counter] Reset",
// payload: {
// value: 0
// }
// }
src/app.component.ts
app/store/counter.actions.ts
import { State, Action, StateContext } from '@ngxs/store';
import { Reset } from '../store/counter.actions';
@State<number>({ name: 'counter', defaults: 0 })
export class CounterState {
@Action(Reset)
Reset(store: StateContext<number>, action: Reset) {
const counter = store.getState();
store.setState(action.payload.value);
}
}
src/app.component.ts
app/store/counter.state.ts
Components
Actions
State
Mutate
Dispatch
Notify
@Component({
template: `
<app-counter
(increment)="increment()" (decrement)="decrement()"
(reset)="reset()">
</app-counter>`
})
export class AppComponent {
constructor(private store: Store) { }
increment = () => this.store.dispatch(new Increment());
decrement = () => this.store.dispatch(new Decrement());
reset = () => this.store.dispatch(new Reset({ value: 0 }));
}
src/app.component.ts
app/app.component.ts
@Component({
template: `
<app-counter [total]="counter|async"></app-counter>`
})
export class AppComponent {
@Select(state => state.counter) counter: Observable<number>;
}
src/app.component.ts
app/app.component.ts
@Component({
selector: 'app-counter',
template: `
<div class="total">{{total}}</div>
<button (click)="increment.emit()">+</button>
<button (click)="decrement.emit()">-</button>
<button (click)="reset.emit()">C</button>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CounterComponent {
@Input() total: number;
@Output() increment = new EventEmitter();
...
}
src/app.component.ts
app/counter/counter.component.ts
Logger
DevTools
Storage
Forms
WebSockets
Router
import { NgxsModule } from '@ngxs/store';
import { NgxsReduxDevtoolsPluginModule }
from '@ngxs/devtools-plugin';
@NgModule({
imports: [
NgxsModule.forRoot([]),
NgxsReduxDevtoolsPluginModule.forRoot()
]
})
export class AppModule {}
src/app.component.ts
import { NgxsModule } from '@ngxs/store';
import { NgxsFormPluginModule }
from '@ngxs/form-plugin';
@NgModule({
imports: [
NgxsModule.forRoot([]),
NgxsFormPluginModule.forRoot(),
NgxsReduxDevtoolsPluginModule.forRoot()
]
})
export class AppModule {}
src/app.component.ts
@State({
name: "app",
defaults: {
form: {
model: undefined,
dirty: false,
status: "",
errors: {}
}
}
})
export class AppState {}
src/app.component.ts
@Component({
selector: 'form',
template: `
<form ngxsForm="app.form" novalidate
[formGroup]="form" (ngSubmit)="onSubmit()">
<input type="text" formControlName="email" />
<button type="submit">Subscribe</button>
</form>`
})
export class FormComponent { }
src/app.component.ts
import { NgxsModule } from '@ngxs/store';
import { NgxsRouterPluginModule }
from '@ngxs/router-plugin';
@NgModule({
imports: [
NgxsModule.forRoot([]),
NgxsRouterPluginModule.forRoot()
]
})
export class AppModule {}
src/app.component.ts
{
todos: [{ id: 1, text: 'todo 1', complete: false }],
currentFilter: "SHOW_ALL"
}
// Filtered Todos
[{ id: 1, text: 'todo 1', complete: false }]
src/app.component.ts
{
todos: [{ id: 1, text: 'todo 1', complete: false }],
currentFilter: "SHOW_COMPLETED"
}
// Filtered Todos
[]
import { FilterState } from '../filter/filter.state';
@State<Todo[]>({ name: 'todos', defaults: [] })
export class TodosState {
@Selector([FilterState]) static todos(state, currentFilter) {
let t = state.slice().reverse();
switch (currentFilter) {
case 'SHOW_ACTIVE': return t.filter(t => !t.completed);
case 'SHOW_COMPLETED': return t.filter(t => t.completed);
case 'SHOW_ALL':
default: return t;
};
}
}
src/app.component.ts
Austin McDaniel