import { Meta, Story } from "@storybook/addon-docs/blocks";
import * as stories from "./standalone.stories.ts";

<Meta of={stories} />

# Standalone Async Actions

These directives should be used when building a standalone button that triggers a long running task
in the background, eg. Refresh buttons. For non-submit buttons that are associated with forms see
[Async Actions In Forms](?path=/story/component-library-async-actions-in-forms-documentation--page).

If the long running background task resolves quickly (e.g. less than 75 ms), the loading spinner
will not display on the button. This prevents an undesirable "flicker" of the loading spinner when
it is not necessary for the user to see it.

## Usage

Adding async actions to standalone buttons requires the following 2 steps:

### 1. Add a handler to your `Component`

A handler is a function that returns a promise or an observable. Functions that return `void` are
also supported which is useful because `return;` can be used to abort an action.

**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler
needs access to the parent component using the variable `this`.

**NOTE:** Handlers do not need to check if any previous requests have finished because the
directives have built in protection against users attempting to trigger new actions before the
previous ones have finished.

#### Example using promises

```ts
@Component({...})
class PromiseExampleComponent {
  handler = async () => {
    await this.apiService.post(/* ... */);
  };
}
```

#### Example using observables

```ts
@Component({...})
class Component {
  handler = () => {
    return this.apiService.post$(/* ... */);
  };
}
```

### 2. Add directive to the DOM element

Add the `bitAction` directive and supply the handler defined in step 1.

**NOTE:** The `directive` is defined using the input syntax: `[input]="handler"`. This is different
from how click handlers are usually defined with the output syntax `(click)="handler()"`.

**NOTE:** `[bitAction]` is used instead of `(click)`. Using both is not supported.

```html
<button bitButton [bitAction]="handler">Do action</button>

<button bitIconButton="bwi-trash" label="Your label here" [bitAction]="handler"></button>`;
```

## Stories

### Promise resolves -- loading spinner is displayed

<Story of={stories.UsingPromise} />

### Promise resolves -- quickly without loading spinner

<Story of={stories.ActionResolvesQuickly} />

### Promise rejects

<Story of={stories.RejectedPromise} />

### Observable

<Story of={stories.UsingObservable} />
