Angular Store Development Workflow
Use when implementing PlatformVmStore state management for lists, CRUD, complex state, or shared/cached data.
Decision Tree
code
What kind of state?
├── Component-scoped CRUD list → @Injectable() + providers: [Store]
├── Shared state between components → @Injectable({ providedIn: 'root' })
├── Form with dependent lookups → @Injectable() + forkJoin for parallel load
├── Cached lookup data → @Injectable({ providedIn: 'root' }) + enableCaching
└── Simple component (no store) → Use AppBaseVmComponent instead
Workflow
- •Search existing stores:
grep "{Feature}Store" --include="*.ts" - •Read design system docs (see Read Directives below)
- •Define state interface with all required properties
- •Implement
vmConstructorwith default state - •Add selectors via
select(), effects viaeffectSimple(), updaters viaupdateState() - •Integrate with component: extend
AppBaseVmStoreComponent, provide store - •Verify checklist below
Key Rules
- •Effects use
effectSimple(fn, 'requestKey')- second param auto-tracks loading state - •State updates must be immutable:
updateState(state => ({ items: [...state.items, newItem] })) - •Selectors are memoized via
select()- returnSignal<T> - •Use
tapResponse(success, error)inside effects - •Component-scoped:
providers: [Store]in@Component - •Singleton cached:
@Injectable({ providedIn: 'root' })+enableCaching
File Location
code
src/Frontend/apps/{app-name}/src/app/features/{feature}/
├── {feature}.store.ts
└── {feature}.component.ts
⚠️ MUST READ Before Implementation
IMPORTANT: You MUST read these files before writing any code. Do NOT skip.
- •⚠️ MUST READ
.claude/skills/shared/angular-design-system.md— hierarchy, platform APIs - •⚠️ MUST READ
.claude/skills/shared/bem-component-examples.md— BEM template examples - •⚠️ MUST READ
.claude/skills/frontend-angular-store/references/store-patterns.md— CRUD, dependent data, caching, integration - •⚠️ MUST READ target app design system:
docs/design-system/06-state-management.md
Anti-Patterns
- •Direct
api.subscribe()withouteffectSimple- no loading state tracking - •
this.currentVm().items.push(newItem)- mutates state directly - •Missing
providers: [Store]in component decorator - •Using
observerLoadingErrorStateinsideeffectSimple(it handles loading internally) - •Store as singleton when it should be component-scoped (or vice versa)
Verification Checklist
- • State interface defines all required properties
- •
vmConstructorprovides default state - • Effects use
effectSimple()with request key - • Effects use
tapResponse()for handling - • Selectors use
select()for memoization - • State updates are immutable
- • Store provided at correct level (component vs root)
- • Caching configured if needed (
enableCaching,cachedStateKeyName)
IMPORTANT Task Planning Notes
- •Always plan and break many small todo tasks
- •Always add a final review todo task to review the works done at the end to find any fix or enhancement needed