Prompt file imported from danielsogl/copilot-workflow-demo (
.github/prompts/ngrx-signals-store-crud.prompt.md). Copyright stays with the author.
NgRx Signal Store CRUD Generator
Goal
Generate a complete NgRx Signal Store with CRUD operations for a specified entity, following the project's architecture patterns and best practices.
Prerequisites
Before running this prompt, ensure you have:
- Entity Definition: The target entity model must be defined and linked in the chat context
- Store Name: Specify the desired store name (e.g.,
UserStore,TaskStore) - Entity Name: Specify the entity name (e.g.,
User,Task)
Instructions
Step 1: Entity and Service Analysis
- Analyze the provided entity model to understand its structure and properties
- Check if an Angular service with HTTP CRUD methods already exists for this entity
- If no service exists, create one with the following demo endpoints based on the entity structure:
// Example endpoints for a User entity getUsers(): Observable<User[]> getUserById(id: string): Observable<User> createUser(user: CreateUserRequest): Observable<User> updateUser(id: string, updates: Partial<User>): Observable<User> deleteUser(id: string): Observable<void>
Step 2: Signal Store Generation
Generate a complete NgRx Signal Store with:
Core Structure
export interface [EntityName]State {
loading: boolean;
error: string | null;
selectedId: string | null;
}
const initial[EntityName]State: [EntityName]State = {
loading: false,
error: null,
selectedId: null,
};
const [entityName]EntityConfig = entityConfig({
entity: type<[EntityName]>(),
collection: '[entityName]',
selectId: ([entityName]: [EntityName]) => [entityName].id,
});
export const [EntityName]Store = signalStore(
{ providedIn: 'root' },
withState(initial[EntityName]State),
withEntities([entityName]EntityConfig),
// ... computed properties
// ... methods
);
Required CRUD Methods
Implement all CRUD operations using rxMethod for Observable-based service calls:
- Load All:
load[EntityName]s(): void - Load By ID:
load[EntityName]ById(id: string): void - Create:
create[EntityName]([entityName]: Create[EntityName]Request): void - Update:
update[EntityName](id: string, updates: Partial<[EntityName]>): void - Delete:
delete[EntityName](id: string): void - Select:
select[EntityName](id: string | null): void
Computed Properties
Include these computed signals:
selected[EntityName]: The currently selected entitytotal[EntityName]Count: Total number of entitieshasData: Whether any entities are loadedisEmpty: Whether the collection is empty
Error Handling
- Use
tapResponsefor proper error handling in all async operations - Set loading states appropriately for all operations
- Clear errors when starting new operations
Step 3: Implementation Details
State Management
- Use
patchStatefor all state updates - Implement proper loading states for each operation
- Handle errors gracefully with user-friendly messages
Entity Operations
- Use atomic entity operations:
addEntity,updateEntity,removeEntity,setAllEntities - Pass
entityConfigto all entity updaters for type safety - Handle optimistic updates where appropriate
Service Integration
- Inject the service using
inject()withinwithMethods - Use
rxMethodfor all Observable-based operations - Never convert Observables to Promises in store methods
Step 4: Integration Guide
Provide example component integration showing:
- Store injection
- Signal binding in templates
- Method calls for CRUD operations
- Loading and error state handling
File Structure
Create the following files in the appropriate domain folder:
src/app/features/[domain]/
└── data/
├── models/
│ └── [entity-name].model.ts # Entity interface & DTOs
├── infrastructure/
│ ├── [entity-name]-api.ts # HttpClient service
│ └── [entity-name]-api.spec.ts # Service tests
└── state/
├── [entity-name]-store.ts # Signal store
└── [entity-name]-store.spec.ts # Store tests
References
- NgRx Signals Patterns - Complete NgRx Signals v21+ architecture and patterns including
withFeature,withLinkedState,withProps,withHooks - Architecture (DDD) - DDD folder structure with
features/wrapper