3.2.0 • Published 1 month ago

@ssv/ngx.command v3.2.0

Weekly downloads
316
License
MIT
Repository
github
Last release
1 month ago

@ssv/ngx.command

npm version

Command pattern implementation for angular. Command's are used to encapsulate information which is needed to perform an action.

Primary usage is to disable a button when an action is executing, or not in a valid state (e.g. busy, invalid), and also to show an activity progress while executing.

Installation

Get library via npm

npm install @ssv/ngx.command

Choose the version corresponding to your Angular version:

Angularlibrary
17+3.x+
10+2.x+
4 to 91.x+

Usage

Command

In order to start working with Command, you need to create a new instance of it.

import { command, commandAsync } from "@ssv/ngx.command";

const isValid = signal(false);
const isValid$ = new BehaviorSubject(false);

// non async
saveCmd = command(() => this.save(), isValid);

// async - returns an observable/promise.
saveCmd = commandAsync(() => Observable.timer(2000), isValid);

// can execute diff ways
saveCmd = command(() => this.save(), () => isValid()); // reactive fn (signal)
saveCmd = command(() => this.save(), isValid); // signal
saveCmd = command(() => this.save(), isValid$); // rx

Command Attribute (Directive)

Handles the command canExecute$, isExecuting and execute functions of the Command, in order to enable/disable, add/remove a cssClass while executing in order alter styling during execution (if desired) and execute when its enabled and clicked.

Generally used on a <button> as below.

Usage

<!-- simple usage -->
<button [ssvCommand]="saveCmd">Save</button>

<!-- using isExecuting + showing spinner -->
<button [ssvCommand]="saveCmd">
  @if(saveCmd.isExecuting) {
    <i class="ai-circled ai-indicator ai-dark-spin small"></i>
  }
  Save
</button>

Usage with params

This is useful for collections (loops) or using multiple actions with different args. NOTE: This will share the isExecuting when used with multiple controls.

<!-- with single param -->
<button [ssvCommand]="saveCmd" [ssvCommandParams]="{id: 1}">Save</button>
<!-- 
  NOTE: if you have only 1 argument as an array, it should be enclosed within an array e.g. [['apple', 'banana']], 
  else it will spread and you will arg1: "apple", arg2: "banana"
-->

 <!-- with multi params -->
<button [ssvCommand]="saveCmd" [ssvCommandParams]="[{id: 1}, 'hello', hero]">Save</button>

Usage with command creator

This is useful for collections (loops) or using multiple actions with different args, whilst not sharing isExecuting.

<button [ssvCommand]="{host: this, execute: removeHero$, canExecute: isValid$, params: [hero, 1337, 'xx']}">Remove</button>
canExecute with params
<button [ssvCommand]="{host: this, execute: removeHero$, canExecute: canRemoveHero$, params: [hero, 1337, 'xx']}">Remove</button>
canRemoveHero$(hero: Hero, id: number, param2): Observable<boolean> {
  return of(id).pipe(
    map(x => x === "invulnerable")
  );
}

Usage without Attribute

It can also be used as below without the command attribute.

<button
    [disabled]="!saveCmd.canExecute"
    (click)="saveCmd.execute()">
    Save
</button>

CommandRef Attribute (directive)

Command creator ref, directive which allows creating Command in the template and associate it to a command (in order to share executions).

@for (hero of heroes; track hero.key) {
  <div #actionCmd="ssvCommandRef" [ssvCommandRef]="{host: this, execute: removeHero$, canExecute: isValid$}" class="button-group">
    <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
      Remove
    </button>
    <button [ssvCommand]="actionCmd.command" [ssvCommandParams]="hero">
      Remove
    </button>
  </div>
}

Utils

canExecuteFromNgForm/canExecuteFromSignals

In order to use with NgForm easily, you can use the following utility method. This will make canExecute respond to form.valid and for form.dirty - also can optionally disable validity or dirty.

import { commandAsync, canExecuteFromNgForm, canExecuteFromSignals } from "@ssv/ngx.command";

loginCmd = commandAsync(x => this.login(), canExecuteFromNgForm(this.form));

// options - disable dirty check
loginCmd = commandAsync(x => this.login(), canExecuteFromNgForm(this.form, {
  dirty: false
}));

// similar functionality using custom signals (or form which provide signals)
loginCmd = commandAsync(x => this.login(), canExecuteFromSignals({dirty: $dirty, valid: $valid}));

Global options

import { provideSsvCommandOptions } from "@ssv/ngx.command";

export const appConfig: ApplicationConfig = {
  providers: [
    provideSsvCommandOptions({
      executingCssClass: "is-busy",
      hasDisabledDelay: false
    }),
  ],
};
3.1.2-dev.51

4 months ago

3.1.2-dev.55

4 months ago

3.2.0-dev.68

1 month ago

3.0.0-dev.42

5 months ago

3.0.0-dev.40

6 months ago

3.2.0

1 month ago

3.1.4-dev.61

4 months ago

3.0.0

5 months ago

3.0.0-dev.28

8 months ago

3.1.3-dev.59

4 months ago

3.1.3-dev.56

4 months ago

4.0.0-dev.67

1 month ago

3.1.3

4 months ago

3.1.2

4 months ago

3.1.0-dev.45

5 months ago

3.1.1

5 months ago

3.1.0

5 months ago

3.0.0-dev.38

6 months ago

3.0.0-dev.36

8 months ago

3.0.0-dev.35

8 months ago

3.0.0-dev.34

8 months ago

3.0.0-dev.32

8 months ago

3.1.1-dev.48

5 months ago

3.0.0-dev.25

8 months ago

3.0.0-dev.1-dev.10

9 months ago

3.0.0-dev.1-dev.11

9 months ago

0.0.0-PLACEHOLDER

9 months ago

3.0.0-dev.19

9 months ago

3.0.0-dev.16

9 months ago

3.0.0-dev.13

9 months ago

3.0.0-dev.23

8 months ago

3.0.0-dev.1

9 months ago

3.0.0-dev.21

9 months ago

3.0.0-dev.20

9 months ago

0.0.0

9 months ago

2.3.0-dev.2

2 years ago

2.3.0-dev.3

2 years ago

2.3.0-dev.4

2 years ago

2.3.0-dev.5

2 years ago

2.3.0-dev.6

2 years ago

2.3.0-dev.7

2 years ago

2.3.2-dev.11

2 years ago

2.3.2

2 years ago

2.3.1

2 years ago

2.3.1-dev.8

2 years ago

2.3.1-dev.9

2 years ago

2.2.0-dev268

3 years ago

2.2.0

3 years ago

2.1.1-dev267

3 years ago

2.1.1

3 years ago

2.1.1-dev246

3 years ago

2.1.0

3 years ago

2.1.0-dev228

3 years ago

2.1.0-dev243

3 years ago

2.0.0

4 years ago

2.0.0-dev217

4 years ago

2.0.0-dev211

5 years ago

1.6.1

5 years ago

2.0.0-dev209

5 years ago

2.0.0-dev207

5 years ago

2.0.0-dev202

5 years ago

1.6.0

5 years ago

2.0.0-dev197

5 years ago

2.0.0-dev198

5 years ago

2.0.0-dev195

5 years ago

1.5.2

5 years ago

1.5.1-dev189

5 years ago

1.5.1-dev186

5 years ago

1.5.1-dev174

5 years ago

1.5.1

5 years ago

1.5.1-dev172

5 years ago

1.5.0-dev168

5 years ago

1.5.0-dev167

5 years ago

1.5.0

5 years ago

1.4.1

6 years ago

1.4.0

6 years ago

1.3.0

6 years ago

1.2.6

6 years ago

1.2.5

6 years ago

1.2.4

6 years ago

1.2.3

6 years ago

1.2.2

6 years ago

1.2.1

6 years ago

1.2.0

6 years ago

1.1.2

7 years ago

1.1.1

7 years ago

1.1.0

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago

1.0.0-rc.2

7 years ago

1.0.0-rc.1

7 years ago

1.0.0-rc.0

8 years ago