This package simplifies dispatching process, you shouldn't care about Store service injection as we provide more declarative way to dispatch events out of the box.
📦 Install
To install @ngxs-labs/dispatch-decorator run the following command:
npm install @ngxs-labs/dispatch-decorator --save
# or if you use yarn
yarn add @ngxs-labs/dispatch-decorator
🔨 Usage
Import the module into your root application module:
import { NgModule } from '@angular/core';
import { NgxsModule } from '@ngxs/store';
import { NgxsDispatchPluginModule } from '@ngxs-labs/dispatch-decorator';
@NgModule({
imports: [
NgxsModule.forRoot(states),
NgxsDispatchPluginModule.forRoot()
]
})
export class AppModule {}
Dispatch
@Dispatch() is a function that allows you to decorate methods and properties of your components, basically arrow functions are properties. Firstly you have to create a state:
import { State, Action, StateContext } from '@ngxs/store';
export class Increment {
public static readonly type = '[Counter] Increment';
}
export class Decrement {
public static readonly type = '[Counter] Decrement';
}
@State<number>({
name: 'counter',
defaults: 0
})
export class CounterState {
@Action(Increment)
public increment({ setState, getState }: StateContext<number>) {
setState(getState() + 1);
}
@Action(Decrement)
public decrement({ setState, getState }: StateContext<number>) {
setState(getState() - 1);
}
}
Register this state in NgxsModule and import this state and actions in your component:
import { Component } from '@angular/core';
import { Select } from '@ngxs/store';
import { Dispatch } from '@ngxs-labs/dispatch-decorator';
import { Observable } from 'rxjs';
import { CounterState, Increment, Decrement } from './counter.state';
@Component({
selector: 'app-root',
template: `
<ng-container *ngIf="counter$ | async as counter">
<h1>{{ counter }}</h1>
</ng-container>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
`
})
export class AppComponent {
@Select(CounterState)
public counter$: Observable<number>;
@Dispatch()
public increment = () => new Increment()
@Dispatch()
public decrement = () => new Decrement()
}
Also, your dispatchers can be asynchronous, they can return Promise or Observable, asynchronous operations are handled outside Angular's zone, thus it doesn't affect performance:
export class AppComponent {
// `ApiService` is defined somewhere
constructor(private api: ApiService) {}
@Dispatch()
public async setAppSchema(): Promise<SetAppSchema> {
const { version, shouldUseGraphQL } = await this.api.getInformation();
const { schema } = await this.api.getSchemaForVersion(version);
return new SetAppSchema(schema);
}
// OR
@Dispatch()
public setAppInformation = () => this.api.getInformation().pipe(
switchMap(({ version }) => this.api.getSchemaForVersion(version)),
map(({ schema }) => new SetAppSchema(schema))
);
}
Notice that it doesn't matter if you use an arrow function or a normal class method.
Dispatching multiple events
Your dispatchers can also return arrays with events inside:
export class AppComponent {
@Dispatch()
public setLanguageAndNavigateHome = (language: string) => {
return [new SetLanguage(language), new Navigate('/')];
}
}