---
name: ssv-ngx-command
description: Implement command pattern in Angular using @ssv/ngx.command library. Use for encapsulating actions with execution state tracking, enabling/disabling controls, and managing async operations. Triggers on button states, action execution, form submissions, or implementing command pattern.
---
# @ssv/ngx.command
Command pattern - encapsulates actions with auto state tracking (`isExecuting`, `canExecute`). Primary use: disable buttons during execution, show loading indicators.
## Creating Commands
**Use `command()` factory** (requires injection context):
```typescript
import { command } from "@ssv/ngx.command";
readonly isValid = signal(false);
readonly saveCmd = command(() => this.save$(), this.isValid);
// Observable, function, boolean also supported
readonly deleteCmd = command(() => this.delete$(), this.isValid$);
readonly computeCmd = command(
() => this.compute(),
() => this.check(),
);
readonly simpleCmd = command(() => this.action()); // No validation
```
## Directive Usage
```html
```
## Parameters
**CRITICAL: Array args must be double-wrapped**:
```html
```
Why: `[items]` spreads. Use `[[items]]` for single array arg.
## Collections (Loops)
**Isolated `isExecuting` per item**:
```html
@for (hero of heroes; track hero.id) {
}
```
```typescript
removeHero$(hero: Hero) {
return this.#http.delete(`/api/heroes/${hero.id}`);
}
```
## Form Integration
```typescript
import { canExecuteFromNgForm, canExecuteFromSignals } from "@ssv/ngx.command";
// NgForm
readonly loginCmd = command(() => this.login$(), canExecuteFromNgForm(this.form()));
// Signal forms
readonly saveCmd = command(() => this.save$(), canExecuteFromSignals({ valid: form.valid, dirty: form.dirty }));
```
## State & Execution
```typescript
cmd.$isExecuting(); // Signal
cmd.$canExecute(); // Signal
cmd.isExecuting; // boolean (deprecated - use signals)
cmd.canExecute; // boolean (deprecated - use signals)
cmd.execute(); // Direct
cmd.execute(arg1, arg2); // With params
await cmd.execute(); // Returns Promise for async
```
## Anti-Patterns
❌ Never use `new Command()` - use `command()` factory
❌ `[ssvCommandParams]="[items]"` spreads - use `[[items]]`
❌ Sharing `isExecuting` in loops - use command creator `{host, execute, params}`
## Common Patterns
```typescript
// Computed validation
readonly canSave = computed(() => this.isValid() && this.hasChanges());
readonly saveCmd = command(() => this.save$(), this.canSave);
// Error handling
readonly saveCmd = command(() =>
this.#http.post('/api/save', data).pipe(
catchError(err => { this.showError(err); return EMPTY; })
)
);
// Loading UI
```
## CommandInput Type
Simplify command input types in child components:
```typescript
import type { CommandInput } from "@ssv/ngx.command";
// Single parameter
readonly onSave = input.required>();
// Multiple parameters
readonly onUpdate = input.required>();
// Instead of verbose:
// readonly onSave = input.required unknown>>();
```
## Global Config
```typescript
import { provideSsvCommandOptions } from "@ssv/ngx.command";
provideSsvCommandOptions({ executingCssClass: "is-busy" });
```
## Advanced
- `references/advanced-patterns.md` - CommandRef, per-item canExecute, CommandInput helper
**Library Ref**: [README](../../../libs/ngx.command/README.md) | [Examples](../../../apps/test-app/src/app/command/) | [Tests](../../../libs/ngx.command/src/command.spec.ts)