> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# $wsActions - Actions

> Trigger frontend actions such as login, address changes, or newsletter sign-up via links or forms and evaluate their success and error results.

With the `$wsActions` module you can trigger actions in the frontend, for example adding a product to the basket, submitting a form, or logging a customer in or out. Afterwards you evaluate the result (success or error).

This page is about triggering and evaluating actions via the `$wsActions` module. Which actions exist and which parameters a single action (e.g. `BasketItemAdd` or `Login`) expects is described in the [actions reference](/en/frontend/referenz/aktionen). There you will find the functional meaning of the individual action names.

***

## Basic concept

An action always goes through the same steps: prepare the action → embed → trigger → read the result → react.

You prepare the action in the template, either as a link with the `url()` function or as a form object with the `create()` function. The customer then triggers the action by clicking or submitting. The shop executes it and rebuilds the target page. On this new page you find the result under `$wsActions.current` and can react accordingly, for example with a success message or by displaying errors.

**Ways to trigger an action**\
For a simple click, for example on the "Add to basket" button, you create a link with the `url()` function. If the customer should enter something (e.g. a login with username and password), you create an action object with `create()` and embed it in a form. The difference therefore lies in whether the customer still enters data or not.

**Execution time:** The template code runs during page rendering. `$wsActions.current` therefore contains the result of the action that was executed in the request with which this page was generated. If no action was executed, `current` is `null` – always check for existence first before accessing results.

### CSRF protection (applies to all actions)

Every action must send a valid [CSRF protection token](/en/frontend/referenz/aktionen#3-2-aktionen-absichern), otherwise the shop rejects the request. This protects against actions being triggered unintentionally from external pages.

When you create actions via `url()` or `create()`, the token is embedded automatically. Only if you assemble a request by hand do you have to pass the token from [`$wsActions.csrfToken`](#wsactions-csrftoken) yourself as the `wscsrf` parameter.

### Availability of `current`

`$wsActions.current` is only filled if an action was executed in the same request. On a normally called page, the value is `null`. That is why the result examples below start with a check: `{{ if $wsActions.current }}`. Without this check, you would be accessing null.

***

## Module overview

**Example / excerpt of** `$wsActions`

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= $wsActions | json }}
```

**JSON output**

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "create": "ƒ()",
  "csrfToken": "...",
  "current": {
    "csrf": "...",
    "error": false,
    "errors": [
      {
        "code": "...",
        "field": "...",
        "subCode": "...",
        "text": "..."
      }
    ],
    "errorsByField": { },
    "globalErrors": [],
    "id": "...",
    "name": "...",
    "params": { },
    "success": true,
    "successInfo": { },
    "tag": "..."
  },
  "url": "ƒ()"
}
```

Note: `"ƒ()"` denotes a function (method). `current` is `null` if no action was executed.

**Variables and methods overview**

| **Name**    | **Return type** | **Description**                                                                                   |
| ----------- | --------------- | ------------------------------------------------------------------------------------------------- |
| `csrfToken` | string          | CSRF protection token of the current session; to be sent as the `wscsrf` parameter.               |
| `current`   | map             | Result of the action that was just executed (success, errors, messages). `null` if no action ran. |
| `create()`  | map             | Creates an action object for use in forms.                                                        |
| `url()`     | string          | Creates a URL that executes a specific action (for links).                                        |

***

## Variables

### \$wsActions.csrfToken

Contains the [CSRF protection token](/en/frontend/referenz/aktionen#3-2-aktionen-absichern) of the current session. You only need it if you assemble an action request manually. In that case it must be sent as the "`wscsrf`" parameter so that the shop accepts the request. With `url()` and `create()` this happens automatically.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<input type="hidden" name="wscsrf" value="{{= $wsActions.csrfToken }}">
```

### \$wsActions.current

Contains the result of the action executed in the current call, i.e. success or error together with messages. The value is `null` if no action was executed.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current }}
  <!-- An action was executed -->
{{ /if }}
```

#### Properties of `$wsActions.current`

| **Property**    | **Return type** | **Description**                                                                                              |
| --------------- | --------------- | ------------------------------------------------------------------------------------------------------------ |
| `name`          | string          | Name of the executed action (e.g. `"BasketItemAdd"`).                                                        |
| `id`            | string          | Unique ID of the action. Format: `<ActionName>:<ActionTag>` if a tag was assigned, otherwise `<ActionName>`. |
| `csrf`          | string          | CSRF token of the executed action.                                                                           |
| `tag`           | string          | Assigned tag of the action, if available.                                                                    |
| `params`        | map             | Parameter values already passed to the action.                                                               |
| `success`       | bool            | Whether the action was successful.                                                                           |
| `successInfo`   | map             | Additional information from the shop on success.                                                             |
| `error`         | bool            | Whether an error occurred.                                                                                   |
| `errors`        | list            | List of all errors that occurred (structure see below).                                                      |
| `errorsByField` | map             | Errors assigned to a field (key = field name).                                                               |
| `globalErrors`  | list            | Errors that cannot be assigned to a field.                                                                   |

<Info>
  The tag (`current.tag`) is currently not evaluated. You can assign it via `create()` to distinguish between several similar actions on the same page.
</Info>

#### Properties of an error (`current.errors[]`)

| **Property** | **Return type** | **Description**                                           |
| ------------ | --------------- | --------------------------------------------------------- |
| `code`       | string          | Error code.                                               |
| `subCode`    | string          | Optional code for more precise specification of `code`.   |
| `field`      | string          | Field where the error occurred (empty for global errors). |
| `text`       | string          | Error text from the configuration.                        |

**Evaluate the name of the action**

Before processing the result, check which action was executed. That way you do not accidentally react to a different action.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current and $wsActions.current.name == "Login" }}
  <!-- Login action was executed -->
{{ /if }}
```

**Evaluate success**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.success }}
  <!-- Action was successful -->
{{ /if }}
```

**Display errors per field**

`errorsByField` assigns errors to an input field. Use this to output an error message directly next to the affected field instead of only a general message.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.errorsByField.zip }}
  <!-- Error in the "zip" field -->
{{ /if }}
```

**List all errors**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $error in $wsActions.current.errors }}
  {{= $error.text }}
{{ /foreach }}
```

***

## Methods

### \$wsActions.create()

Creates an action object for use in forms. Use `create()` when the customer still enters data before triggering (e.g. login data). The object provides the values (among others `id` and `csrf`) that you can embed as hidden form fields. The object has the same properties as `$wsActions.current`.

**Signature**\
`$wsActions.create(actionName, paramDefaults, target, tag)`

**Return value**\
`map` – the action object.

**Parameters**

| **Name**        | **Type** | **Required** | **Description**                                                                                    |
| --------------- | -------- | ------------ | -------------------------------------------------------------------------------------------------- |
| `actionName`    | string   | yes          | Name of the action to be executed (e.g. `"BasketItemAdd"`).                                        |
| `paramDefaults` | map      | no           | Preset parameters that can still be changed when the action is executed (e.g. a default quantity). |
| `target`        | string   | no           | Target page after successful execution.                                                            |
| `tag`           | string   | no           | Freely chosen label to distinguish between multiple actions.                                       |

**Example** that creates a basket action:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $action = $wsActions.create("BasketItemAdd", { productId: "12345", quantity: 1 }) }}
ID: {{= $action.id }}
CSRF: {{= $action.csrf }}
```

### \$wsActions.url()

Creates a URL that executes a specific action. Use `url()` for a link where the customer does not enter any further data (e.g. "Add to basket" or "Log out").

**Signature**\
`$wsActions.url(action, target, params)`

**Return value**\
`string` – the URL that executes the action.

**Parameters**

| **Name** | **Type** | **Required** | **Description**                              |
| -------- | -------- | ------------ | -------------------------------------------- |
| `action` | string   | yes          | Name of the action to be executed.           |
| `target` | string   | yes          | Target page after successful execution.      |
| `params` | map      | yes          | Parameters of the action (e.g. `productId`). |

**Example** that creates a link for adding to the basket:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<a href="{{= $wsActions.url('BasketItemAdd', $wsViews.current.url(), { productId: '12345', quantity: 1 }) }}">
  Add to basket
</a>
```

<Info>
  The function `$wsViews.current.url()` comes from the [\$wsViews](/en/frontend/referenz/module/wsviews) module and returns the current page as the target. This keeps the customer on the same page after adding.
</Info>

***

## Examples

### Add a product to the basket and evaluate the result

This example shows the complete flow: the link triggers the action, after the click the page is rebuilt, and `current` is evaluated.

<Note>
  `productId` is a placeholder and must be replaced with the ID of an existing product. A non-existent product ID does not result in an evaluable `current.error`; it may cause the request to fail on the server side.
</Note>

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<!-- 1. Trigger: link that executes the action -->
<a href="{{= $wsActions.url('BasketItemAdd', $wsViews.current.url(), { productId: '12345', quantity: 1 }) }}">
  Add to basket
</a>

<!-- 2. After the click: evaluate the result of the same action -->
{{ if $wsActions.current and $wsActions.current.name == "BasketItemAdd" }}
  {{ if $wsActions.current.success }}
    Product was added to the basket.
  {{ else }}
    {{ foreach $error in $wsActions.current.errors }}
      {{= $error.text }}
    {{ /foreach }}
  {{ /if }}
{{ /if }}
```

**Result** \
After the click the customer stays on the page and sees either a confirmation or the concrete error messages from the action.

### Login form with field errors

Here the customer enters data, so the action is prepared with `create()` and embedded in a form. After submitting, errors are displayed directly at the affected field.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $login = $wsActions.create("Login", { }, $wsViews.current.url()) }}

<form method="post" action="{{= $wsViews.current.url() }}">
  <input type="hidden" name="wsact" value="{{= $login.id }}">
  <input type="hidden" name="wscsrf" value="{{= $login.csrf }}">
  <input type="hidden" name="wstarget" value="{{= $wsViews.current.url() }}">

  <input type="text" name="username">
  {{ if $wsActions.current.errorsByField.username }}
    <span class="fehler">{{= $wsActions.current.errorsByField.username }}</span>
  {{ /if }}

  <input type="password" name="password">
  <button type="submit">Log in</button>
</form>
```

**Result** \
If the data is incorrect, the error message appears directly below the affected field.

***

## Further links

* [Actions (concept and reference)](/en/frontend/referenz/aktionen) – what actions are, how they are secured, and which action names exist with which parameters. This page only shows access via `$wsActions`.
* [\$wsViews](/en/frontend/referenz/module/wsviews) – with `current.url()` and `viewUrl()` it provides the target pages that `url()` and `create()` expect as `target`.

With the `$wsActions` module you can trigger actions in the frontend, for example adding a product to the basket, submitting a form, or logging a customer in or out. Afterwards you evaluate the result (success or error).

This page is about triggering and evaluating actions via the `$wsActions` module. Which actions exist and which parameters a single action (e.g. `BasketItemAdd` or `Login`) expects is described in the [actions reference](/en/frontend/referenz/aktionen). There you will find the functional meaning of the individual action names.

## Basic concept

An action always goes through the same steps: prepare the action → embed → trigger → read the result → react.

You prepare the action in the template, either as a link with the `url()` function or as a form object with the `create()` function. The customer then triggers the action by clicking or submitting. The shop executes it and rebuilds the target page. On this new page you find the result under `$wsActions.current` and can react accordingly, for example with a success message or by displaying errors.

**Ways to trigger an action**\
For a simple click, for example on the "Add to basket" button, you create a link with the `url()` function. If the customer should enter something (e.g. a login with username and password), you create an action object with `create()` and embed it in a form. The difference therefore lies in whether the customer still enters data or not.

**Execution time:** The template code runs during page rendering. `$wsActions.current` therefore contains the result of the action that was executed in the request with which this page was generated. If no action was executed, `current` is `null` – always check for existence first before accessing results.

### CSRF protection (applies to all actions)

Every action must send a valid [CSRF protection token](/en/frontend/referenz/aktionen#3-2-aktionen-absichern), otherwise the shop rejects the request. This protects against actions being triggered unintentionally from external pages.

When you create actions via `url()` or `create()`, the token is embedded automatically. Only if you assemble a request by hand do you have to pass the token from [`$wsActions.csrfToken`](#wsactions-csrftoken) yourself as the `wscsrf` parameter.

### Availability of `current`

`$wsActions.current` is only filled if an action was executed in the same request. On a normally called page, the value is `null`. That is why the result examples below start with a check: `{{ if $wsActions.current }}`. Without this check, you would be accessing null.

***

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "create": "ƒ()",
  "csrfToken": "...",
  "current": {
    "csrf": "...",
    "error": false,
    "errors": [
      {
        "code": "...",
        "field": "...",
        "subCode": "...",
        "text": "..."
      }
    ],
    "errorsByField": { },
    "globalErrors": [],
    "id": "...",
    "name": "...",
    "params": { },
    "success": true,
    "successInfo": { },
    "tag": "..."
  },
  "url": "ƒ()"
}
```

Note: `"ƒ()"` denotes a function (method). `current` is `null` if no action was executed.

| **Name**    | **Return type** | **Description**                                                                                   |
| ----------- | --------------- | ------------------------------------------------------------------------------------------------- |
| `csrfToken` | string          | CSRF protection token of the current session; to be sent as the `wscsrf` parameter.               |
| `current`   | map             | Result of the action that was just executed (success, errors, messages). `null` if no action ran. |
| `create()`  | map             | Creates an action object for use in forms.                                                        |
| `url()`     | string          | Creates a URL that executes a specific action (for links).                                        |

Contains the [CSRF protection token](/en/frontend/referenz/aktionen#3-2-aktionen-absichern) of the current session. You only need it if you assemble an action request manually. In that case it must be sent as the "`wscsrf`" parameter so that the shop accepts the request. With `url()` and `create() `this happens automatically.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<input type="hidden" name="wscsrf" value="{{= $wsActions.csrfToken }}">
```

Contains the result of the action executed in the current call, i.e. success or error together with messages. The value is `null` if no action was executed.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current }}
  <!-- An action was executed -->
{{ /if }}
```

#### Properties of `$wsActions.current`

| **Property**    | **Return type** | **Description**                                                                                              |
| --------------- | --------------- | ------------------------------------------------------------------------------------------------------------ |
| `name`          | string          | Name of the executed action (e.g. `"BasketItemAdd"`).                                                        |
| `id`            | string          | Unique ID of the action. Format: `<ActionName>:<ActionTag>` if a tag was assigned, otherwise `<ActionName>`. |
| `csrf`          | string          | CSRF token of the executed action.                                                                           |
| `tag`           | string          | Assigned tag of the action, if available.                                                                    |
| `params`        | map             | Parameter values already passed to the action.                                                               |
| `success`       | bool            | Whether the action was successful.                                                                           |
| `successInfo`   | map             | Additional information from the shop on success.                                                             |
| `error`         | bool            | Whether an error occurred.                                                                                   |
| `errors`        | list            | List of all errors that occurred (structure see below).                                                      |
| `errorsByField` | map             | Errors assigned to a field (key = field name).                                                               |
| `globalErrors`  | list            | Errors that cannot be assigned to a field.                                                                   |

<Info>
  The tag (`current.tag`) is currently not evaluated. You can assign it via `create()` to distinguish between several similar actions on the same page.
</Info>

#### Properties of an error (`current.errors[]`)

| **Property** | **Return type** | **Description**                                           |
| ------------ | --------------- | --------------------------------------------------------- |
| `code`       | string          | Error code.                                               |
| `subCode`    | string          | Optional code for more precise specification of `code`.   |
| `field`      | string          | Field where the error occurred (empty for global errors). |
| `text`       | string          | Error text from the configuration.                        |

**Evaluate the name of the action**

Before processing the result, check which action was executed. That way you do not accidentally react to a different action.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current and $wsActions.current.name == "Login" }}
  <!-- Login action was executed -->
{{ /if }}
```

**Evaluate success**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.success }}
  <!-- Action was successful -->
{{ /if }}
```

**Display errors per field**

`errorsByField` assigns errors to an input field. Use this to output an error message directly next to the affected field instead of only a general message.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.errorsByField.zip }}
  <!-- Error in the "zip" field -->
{{ /if }}
```

**List all errors**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $error in $wsActions.current.errors }}
  {{= $error.text }}
{{ /foreach }}
```

***

## Methods

### \$wsActions.create()

Creates an action object for use in forms. Use `create()` when the customer still enters data before triggering (e.g. login data). The object provides the values (among others `id` and `csrf`) that you can embed as hidden form fields. The object has the same properties as `$wsActions.current`.

**Signature**\
`$wsActions.create(actionName, paramDefaults, target, tag)`

**Return value**\
`map` – the action object.

**Parameters**

| **Name**        | **Type** | **Required** | **Description**                                                                                    |
| --------------- | -------- | ------------ | -------------------------------------------------------------------------------------------------- |
| `actionName`    | string   | yes          | Name of the action to be executed (e.g. `"BasketItemAdd"`).                                        |
| `paramDefaults` | map      | no           | Preset parameters that can still be changed when the action is executed (e.g. a default quantity). |
| `target`        | string   | no           | Target page after successful execution.                                                            |
| `tag`           | string   | no           | Freely chosen label to distinguish between multiple actions.                                       |

**Example** that creates a basket action:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $action = $wsActions.create("BasketItemAdd", { productId: "12345", quantity: 1 }) }}
ID: {{= $action.id }}
CSRF: {{= $action.csrf }}
```

### \$wsActions.url()

Creates a URL that executes a specific action. Use `url()` for a link where the customer does not enter any further data (e.g. "Add to basket" or "Log out").

**Signature**\
`$wsActions.url(action, target, params)`

**Return value**\
`string` – the URL that executes the action.

**Parameters**

| **Name** | **Type** | **Required** | **Description**                              |
| -------- | -------- | ------------ | -------------------------------------------- |
| `action` | string   | yes          | Name of the action to be executed.           |
| `target` | string   | yes          | Target page after successful execution.      |
| `params` | map      | yes          | Parameters of the action (e.g. `productId`). |

**Example** that creates a link for adding to the basket:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<a href="{{= $wsActions.url('BasketItemAdd', $wsViews.current.url(), { productId: '12345', quantity: 1 }) }}">
  Add to basket
</a>
```

<Info>
  The function `$wsViews.current.url()`comes from the [\$wsViews](/en/frontend/referenz/module/wsviews) module and returns the current page as the target. This keeps the customer on the same page after adding.
</Info>

## Examples

### Add a product to the basket and evaluate the result

This example shows the complete flow: the link triggers the action, after the click the page is rebuilt, and `current` is evaluated.

<Note>
  `productId` is a placeholder and must be replaced with the ID of an existing product. A non-existent product ID does not result in an evaluable `current.error`; it may cause the request to fail on the server side.
</Note>

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<!-- 1. Trigger: link that executes the action -->
<a href="{{= $wsActions.url('BasketItemAdd', $wsViews.current.url(), { productId: '12345', quantity: 1 }) }}">
  Add to basket
</a>

<!-- 2. After the click: evaluate the result of the same action -->
{{ if $wsActions.current and $wsActions.current.name == "BasketItemAdd" }}
  {{ if $wsActions.current.success }}
    Product was added to the basket.
  {{ else }}
    {{ foreach $error in $wsActions.current.errors }}
      {{= $error.text }}
    {{ /foreach }}
  {{ /if }}
{{ /if }}
```

**Result** \
After the click the customer stays on the page and sees either a confirmation or the concrete error messages from the action.

### Login form with field errors

Here the customer enters data, so the action is prepared with `create()` and embedded in a form. After submitting, errors are displayed directly at the affected field.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $login = $wsActions.create("Login", { }, $wsViews.current.url()) }}

<form method="post" action="{{= $wsViews.current.url() }}">
  <input type="hidden" name="wsact" value="{{= $login.id }}">
  <input type="hidden" name="wscsrf" value="{{= $login.csrf }}">
  <input type="hidden" name="wstarget" value="{{= $wsViews.current.url() }}">

  <input type="text" name="username">
  {{ if $wsActions.current.errorsByField.username }}
    <span class="fehler">{{= $wsActions.current.errorsByField.username }}</span>
  {{ /if }}

  <input type="password" name="password">
  <button type="submit">Log in</button>
</form>
```

**Result** \
If the data is incorrect, the error message appears directly below the affected field.

## Further links

* [Actions (concept and reference)](/en/frontend/referenz/aktionen) – what actions are, how they are secured, and which action names exist with which parameters. This page only shows access via `$wsActions`.
* [\$wsViews](/en/frontend/referenz/module/wsviews) – with `current.url()` and `viewUrl()` it provides the target pages that `url()` and `create()` expect as `target`.
