This package contains utilities for using XState with Angular.
ngx-xstate
requires Angular 15+. All tests were carried out using the standalone components approach. You can use Nx Angular Standalone Project or Angular CLI.
To get started with ngx-xstate
, simply install the library using NPM:
npm i xstate ngx-xstate
To use ngx-xstate
, create a new component inside your angular project. Create a statechart using the createMachine
API and add it to your component using inject(XStateService)
. For example:
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { NgxXStateModule, XStateService } from 'ngx-xstate';
import { createMachine } from 'xstate';
type Data = Record<string, unknown>;
interface DataMachineContext {
data: Data[];
error: Error | null;
}
type DataMachineEvent = { type: 'FETCH' } | { type: 'RETRY' } | { type: 'LOADED'; data: Data[] } | { type: 'ERROR'; message: string };
export const dataMachine = createMachine({
id: 'dataMachine',
predictableActionArguments: true,
schema: {
context: {} as DataMachineContext,
events: {} as DataMachineEvent,
},
initial: 'idle',
context: {
data: [],
error: null,
},
states: {
idle: { on: { FETCH: 'loading' } },
loading: {
invoke: {
src: 'fetchData',
onError: {
target: 'failure',
actions: assign({
error: (_, event) => new Error(event.data),
}),
},
},
on: {
LOADED: {
target: 'success',
actions: [
assign({
data: (_, event) => event.data,
}),
],
},
},
},
success: {},
failure: { on: { RETRY: 'loading' } },
},
});
@Component({
standalone: true,
imports: [CommonModule, HttpClientModule, NgxXStateModule],
selector: 'example-app',
template: `
<h1>Hello XState from Angular!</h1>
<button (click)="actor.send({ type: 'FETCH' })">Load</button>
<hr />
<ng-container *ngIf="{ state: (actor.state$ | async)! } as vm" [ngSwitch]="true">
<ng-container *ngSwitchCase="vm.state.matches('loading')">Loading...</ng-container>
<ng-container *ngSwitchCase="vm.state.matches('success')">
<div *ngFor="let item of vm.state.context.data">
{{ item['title'] }}
</div>
</ng-container>
<ng-container *ngSwitchCase="vm.state?.matches('failure')">{{ vm.state.context.error?.message }}</ng-container>
</ng-container>
`,
})
export class AppComponent {
http = inject(HttpClient);
actor = inject(XStateService).useMachine<typeof dataMachine>(dataMachine, {
services: {
fetchData: () => (send) => {
this.http.get<Data[]>('https://jsonplaceholder.typicode.com/posts').subscribe((data) => {
return send({
type: 'LOADED',
data,
});
});
},
},
devTools: true,
});
}
If you're interested in contributing to ngx-xstate
, please feel free to submit a pull request or open an issue on GitHub. We welcome all contributions and feedback!
ngx-xstate
is licensed under the MIT license. See the LICENSE file for more information.