Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

@ngstato/angular

NgRx requires 9 concepts for an async action. ngStato requires 1.

Angular Signals. Dependency injection. Built-in DevTools. ~1 KB.

npm Angular gzip license

Documentation · Angular Guide · API Reference


Install

npm install @ngstato/core @ngstato/angular

Full 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

becher.github.io/ngStato

Start in 5 min · Angular guide · Testing · CRUD recipe · NgRx migration · API

License

MIT