@ngstato/angular
v0.4.2
Published
ngStato — Angular adapter with native Signals
Maintainers
Readme
@ngstato/angular
NgRx requires 9 concepts for an async action. ngStato requires 1.
Angular Signals. Dependency injection. Built-in DevTools. ~1 KB.
Documentation · Angular Guide · API Reference
Install
npm install @ngstato/core @ngstato/angularFull working example — 3 files
1. Config — one-time setup:
// app.config.ts
provideStato({
http: { baseUrl: 'https://api.example.com' },
devtools: isDevMode()
})2. Store — state + actions + selectors in one object:
// users.store.ts
import { createStore, http, connectDevTools } from '@ngstato/core'
import { StatoStore } from '@ngstato/angular'
export const UsersStore = StatoStore(() => {
const store = createStore({
users: [] as User[],
loading: false,
error: null as string | null,
selectors: {
total: (s) => s.users.length,
admins: (s) => s.users.filter(u => u.role === 'admin')
},
actions: {
async loadUsers(state) {
state.loading = true
state.users = await http.get('/users')
state.loading = false
},
async deleteUser(state, id: string) {
await http.delete(`/users/${id}`)
state.users = state.users.filter(u => u.id !== id)
}
},
hooks: { onInit: (s) => s.loadUsers() }
})
connectDevTools(store, 'Users')
return store
})3. Component — everything is a Signal:
// users.component.ts
@Component({
template: `
@if (store.loading()) { <spinner /> }
<h2>Users ({{ store.total() }})</h2>
@for (user of store.users(); track user.id) {
<div>
{{ user.name }}
<button (click)="store.deleteUser(user.id)">×</button>
</div>
}
`
})
export class UsersComponent {
store = injectStore(UsersStore)
}That's the entire pattern. No reducers, no effects class, no action creators, no selectors file.
What you get
| What you define | What Angular gets |
|:--|:--|
| users: [] (state) | store.users() → WritableSignal |
| total: (s) => s.users.length (selector) | store.total() → computed Signal (memoized) |
| async loadUsers(state) { ... } (action) | store.loadUsers() → Promise<void> |
All Signals update automatically. Zero manual subscriptions.
DevTools — zero install, all browsers
<stato-devtools />- Draggable, resizable, minimizable panel
- Action history with timestamps and duration
- State diffs — before/after for every action
- Current state explorer
- Works on mobile
- Impossible to enable in production (
isDevMode())
| | NgRx | ngStato |
|:--|:--|:--|
| Setup | Chrome extension | <stato-devtools /> |
| Mobile | ❌ | ✅ |
| Prod safety | Manual | Automatic |
Why teams switch
| | NgRx v21 | @ngstato |
|:--|:--|:--|
| Bundle | ~50 KB gzip | ~4 KB (core + angular) |
| Async action | rxMethod + pipe + tap + switchMap + from + tapResponse + patchState | async/await |
| CRUD store | ~90 lines, 3+ files | ~45 lines, 1 file |
| DevTools | Chrome only | All browsers + mobile |
| Entity adapter | ✅ | ✅ |
| Feature composition | ✅ | ✅ mergeFeatures() |
| Concurrency | RxJS operators | ✅ exclusive queued abortable |
| Testing | provideMockStore | ✅ createMockStore() |
| Persistence | Custom meta-reducers | ✅ withPersist() |
📖 Documentation
Start in 5 min · Angular guide · Testing · CRUD recipe · NgRx migration · API
License
MIT
