craftState
Creates a state definition for use within a craft store, enabling reactive state management with optional custom methods and computed values.
Import
typescript
import { craftState } from '@ng-angular-stack/craft';Introduction
craftState integrates a state() instance into a craft store by:
- Registering the state under a specific name in the store
- Automatically prefixing custom methods and computed values with the state name
- Providing type-safe access to state, methods, and computed properties
- Enabling reactive connections to sources, inputs, and other store states
- Supporting insertions for extended functionality
Naming Convention
- The state is accessible as
store.stateName(returns the Signal) - Custom methods are prefixed:
store.stateNameMethodName - Computed values are prefixed:
store.stateNameComputedName
Use Cases
- Local UI state: Form values, filters, pagination, modal visibility
- Derived state: Computed values based on state changes
- Coordinated state: State that reacts to other states or sources
- Encapsulated logic: State with associated behavior methods
Integration
- Access to other craft entries (sources, queries, mutations) via context
- React to sources using
afterRecomputation() - Supports all
state()insertion features (persistence, validation, etc.)
Signature
ts
function craftState<Context, StoreConfig, StateName, State, Insertions>(
stateName: StateName,
stateFactory: (
context: CraftFactoryEntries<Context>,
) => StateOutput<State, Insertions>,
): CraftStateOutputs<Context, StoreConfig, StateName, State, Insertions>;Parameters
stateName
The name under which this state will be registered in the store. Used as prefix for all methods and computed values.
stateFactory
Factory function that receives the craft context and returns a state() instance. Has access to all other craft entries (sources, queries, mutations, states) defined before it.
Return Value
A craft factory utility that integrates the state into the store with:
store.stateName: Signal returning the current state valuestore.stateNameMethodName: Prefixed custom methods from insertionsstore.stateNameComputedName: Prefixed computed signals from insertions
Examples
Basic state without methods
ts
const { injectCraft } = craft(
{ name: '', providedIn: 'root' },
craftState('counter', () => state(0)),
);
const store = injectCraft();
console.log(store.counter()); // 0
store.counter.set(5);
console.log(store.counter()); // 5State with custom methods
ts
const { injectCraft } = craft(
{ name: '', providedIn: 'root' },
craftState('todos', () =>
state([] as Todo[], ({ state, set }) => ({
add: (todo: Todo) => {
set([...state(), todo]);
},
remove: (id: string) => {
set(state().filter((t) => t.id !== id));
},
clear: () => {
set([]);
},
})),
),
);
const store = injectCraft();
store.todosAdd({ id: '1', text: 'Buy milk', done: false });
store.todosAdd({ id: '2', text: 'Walk dog', done: false });
console.log(store.todos().length); // 2
store.todosRemove('1');
console.log(store.todos().length); // 1
store.todosClear();
console.log(store.todos().length); // 0State reacting to sources
ts
const { injectCraft } = craft(
{ name: '', providedIn: 'root' },
craftSources({
resetFilters: source<void>(),
}),
craftState('filters', ({ resetFilters }) =>
state(
{ search: '', category: 'all', priceRange: [0, 1000] },
({ state, set }) => ({
setSearch: (search: string) => {
set({ ...state(), search });
},
setCategory: (category: string) => {
set({ ...state(), category });
},
reset: afterRecomputation(resetFilters, () => {
set({ search: '', category: 'all', priceRange: [0, 1000] });
}),
}),
),
),
);
const store = injectCraft();
store.filtersSetSearch('laptop');
store.filtersSetCategory('electronics');
console.log(store.filters()); // { search: 'laptop', category: 'electronics', ... }
store.setResetFilters();
console.log(store.filters()); // { search: '', category: 'all', ... }Craft Utilities
Links to all craft utilities implemented in libs/core/src/lib: