> ## 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.

# Aktionen - Übersicht

> Übersicht aller Aktionen der Template-Sprache: Eingaben des Nutzers für Warenkorb, Login, Registrierung und mehr verarbeiten und Ergebnisse auswerten.

Aktionen sind das Bindeglied zwischen dem, was ein Benutzer im Shop macht, und dem, was der Shop daraufhin ausführt. Ob ein Kunde ein Produkt in den Warenkorb legt, sich registriert oder einloggt - hinter jedem dieser Vorgänge steckt eine Aktion.

Aktionen nehmen die Eingaben des Benutzers entgegen, verarbeiten sie im Hintergrund und geben dem Frontend zurück, ob alles geklappt hat oder ein Fehler aufgetreten ist.

***

## Grundprinzip

Der Shop stellt eine Reihe vordefinierter Aktionen bereit. Diese sind vom System vorgegeben und können nicht frei benannt werden. Jede Aktionen hat einen festen Namen, zum Beispiel `BasketItemAdd` (Produkt in den Warenkorb legen), `Login` (Benutzer einloggen) oder `AccountRegister` (neues Konto anlegen).

Aktionen können auf drei Arten ausgeführt werden:

* Über ein Formular - der häufigste Fall. Der Benutzer füllt ein Formular aus und sendet es ab.
* Über einen Link - für Aktionen ohne Benutzereingaben, zum Beispiel das Ausloggen.
* Per AJAX - wenn die Seite nach der Ausführung nicht neu geladen werden soll.

Unabhängig davon, wie eine Aktion ausgeführt wird, läuft im Hintergrund immer derselbe Prozess ab: Der Shop empfängt die Anfrage, verarbeitet sie und gibt zurück, ob die Aktion erfolgreich war oder ein Fehler aufgetreten ist.

Einige Aktionen Verhalten sich abweichend und geben statt einer neuen Seite direkt Daten zurück, zum Beispiel als JSON im Rahmen des Checkouts. Dieses abweichende Verhalten ist bei den betreffenden Aktionen jeweils dokumentiert.

***

## Aktionen vorbereiten

Bevor eine Aktion in einem Template genutzt werden kann, muss ein sogenanntes Aktionsobjekt erstellt werden. Man kann es sich wie einen Behälter vorstellen, der alles enthält, was für die Ausführung der Aktion benötigt wird und nach dem Absenden auch die Rückmeldung des Shops enthält.

Das Aktionsobjekt wird mit [\$wsActions.create()](/frontend/referenz/module/wsactions#%24wsactions-create) erstellt, wobei der Name der gewünschten Aktion übergeben wird:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myAction = $wsActions.create("BasketItemAdd") }}
```

Optional kann hier bereits die Zielseite, auf die nach erfolgreicher Ausführung der Aktion weitergeleitet wird, mitgegeben werden:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myAction = $wsActions.create("BasketItemAdd", target=$wsViews.viewUrl('basket.htm')) }}
```

Das Objekt löst dabei noch nicht aus, es bereitet lediglich die Aktion vor. Die Aktion selbst wird erst ausgeführt, wenn der Benutzer das Formular absendet, auf einen Link klickt oder eine AJAX-Anfrage abgesendet wird.

Nach der Ausführung befüllt der Shop das Aktionsobjekt automatisch mit Rückmeldungen. Im Template kann dann über die Variable `$myAction` darauf zugegriffen werden, zum Beispiel mit `$myAction.success` oder `$myAction.errors`. Eine vollständige Beschreibung aller verfügbaren Eigenschaften findet sich in der [\$wsActions Modulreferenz](/frontend/referenz/module/wsactions).

| **Eigenschaft**   | **Beschreibung**                                                                                                                                       |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `$action.id`      | Die ID der Aktion, die im Formular benötigt wird, damit der Shop weiß, was ausgeführt werden soll.                                                     |
| `$action.csrf`    | Ein Sicherheits-Token, das jede Anfrage absichert (mehr dazu [hier](#3-2-1-csrf-schutz)).                                                              |
| `$action.success` | Ist `true`, wenn die Aktion erfolgreich ausgeführt wurde.                                                                                              |
| `$action.error`   | Ist `true`, wenn ein Fehler aufgetreten ist.                                                                                                           |
| `$action.errors`  | Eine Liste aller aufgetretenen Fehler mit Fehlercode, betroffenem Feld und optionalem Detail.                                                          |
| `$action.params`  | Die zuletzt eingegebenen Werte. Nützlich, um ein Formular bei einem Fehler vorausgefüllt anzuzeigen, damit der Benutzer nicht alles neu eingeben muss. |

***

## Aktionen ausführen

### Ausführung über Formulare

Der häufigste Weg, eine Aktion auszuführen, ist ein HTML-Formular. Das vorbereitete Aktionsobjekt wird in das Formular eingebunden und die Aktion wird ausgeführt, sobald der Benutzer das Formular absendet.

Das Formular wird immer an die URL der aktuellen Seite gesendet, damit der Shop nach der Ausführung dieselbe Seite neu aufbauen und die Rückmeldung anzeigen kann:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<form method="POST" action="{{= $wsViews.current.url() }}">
```

Jedes Formular, das eine Aktion ausführt, benötigt drei Pflichtfelder:

| **Feld**   | **Wert**                                     | **Beschreibung**                                                                                                                                                               |
| ---------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `wsact`    | `{{= $action.id }}`                          | Teilt dem Shop mit, welche Aktion ausgeführt werden soll.                                                                                                                      |
| `wscsrf`   | `{{= $action.csrf }}`                        | Ein Sicherheits-Token zum Schutz vor unerlaubten Zugriffen (siehe LINK HIER EINFÜGEN).                                                                                         |
| `wstarget` | `z.B. {{= $wsViews.viewUrl('basket.htm') }}` | Die Seite, auf die der Benutzer nach erfolgreicher Ausführung weitergeleitet wird. Die Weiterleitung verhindert außerdem, dass ein Seiten-Reload das Formular erneut absendet. |

Zusätzlich zu den Pflichtfeldern enthält das Formular die aktionsspezifischen Felder. Welche das sind, ist in der jeweiligen Aktionsdokumentation beschrieben.

Das folgende Beispiel zeigt ein vollständiges Formular zum Hinzufügen eines Produkts in den Warenkorb:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myAction = $wsActions.create("BasketItemAdd") }}
<form method="POST" action="{{= $wsViews.current.url() }}">
  <input type="hidden" name="wsact"     value="{{= $myAction.id }}">
  <input type="hidden" name="wscsrf"    value="{{= $myAction.csrf }}">
  <input type="hidden" name="wstarget"  value="{{= $wsViews.viewUrl('basket.htm') }}">
  <input type="hidden" name="productId" value="12345">
  <input type="number" name="quantity"  value="1">
  <button type="submit">In den Warenkorb</button>
</form>
```

### Tags - mehrere Formulare derselben Aktionsart unterscheiden

Wenn auf einer Seite mehrere Formulare derselben Aktionsart vorkommen, zum Beispiel ein “In den Warenkorb”-Button in jeder Produktbox einer Kategorieseite, teilen sich alle diese Formulare standardmäßig dieselben Rückmeldungen. Das bedeutet: Tritt bei einem Produkt ein Fehler auf, würden alle Formulare auf der Seite diesen Fehler anzeigen.

Mit einem Tag lässt sich jede Aktion eindeutig unterscheiden. Als Tag eignet sich zum Beispiel die Produkt-ID:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $action = $wsActions.create("BasketItemAdd", tag=$product.id) }}
```

Der Shop erzeugt daraus eine eindeutige ID im Format `BasketItemAdd:42` (wobei `42` in diesem Beispiel die Produkt-ID wäre). Dadurch erhält jedes Produkt ein eigenes Aktionsobjekt und Fehler erscheinen nur beim betreffenden Formular.

Bei einigen Aktionen, insbesondere im Checkout, wird der Tag genutzt, um den Adresstyp direkt im Aktionsnamen festzulegen:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $commitBillAction     = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ var $commitShippingAction = $wsActions.create("CheckoutCommitDraftAddress:shipping") }}
```

### Aktionen absichern

Aktionen können auf zwei Arten gegen unerlaubte Zugriffe geschützt werden - durch einen CSRF-Token, der bei jeder Aktion Pflicht ist und optional durch ein Captcha.

### CSRF-Schutz

CSRF (`Cross-Site Request Forgery`) bezeichnet einen Angriff, bei dem eine externe Website im Namen eines eingeloggten Benutzers unbemerkt Anfragen an den Shop sendet, zum Beispiel um eine Bestellung auszulösen oder Kontodaten zu ändern. Der CSRF-Schutz verhindert, dass solche Anfragen vom Shop akzeptiert werden.

Dazu wird für jede Benutzersitzung ein einmaliger CSRF-Token erzeugt. Weil der Token an die aktuelle Sitzung gebunden ist, kann eine fremde Website ihn nicht kennen und die Aktion damit nicht unbemerkt auslösen. Der Token steht direkt am Aktionsobjekt zur Verfügung und wird so eingebunden:

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

### Captcha-Schutz

Für bestimmte Aktionen, zum Beispiel die Registrierung oder ein Kontaktformular, kann zusätzlich ein Captcha aktiviert werden. Ein Captcha ist eine Sicherheitsabfrage, die sicherstellt, dass das Formular von einem echten Menschen ausgefüllt wird und nicht von einem automatisierten Bot.

Ist der Captcha-Schutz für eine Aktion aktiv, wird die Aktion nur ausgeführt, wenn der Benutzer das Captcha erfolgreich gelöst hat. Schlägt die Prüfung fehl, wird die Aktion nicht ausgeführt.

Damit der Schutz greift, sind zwei Voraussetzungen nötig:

1. Die Aktion muss in der [Shop-Konfiguration](/konfiguration/security-sicherheitsregeln) unter `security.actionGuard` für den Captcha-Schutz eingetragen sein.
2. Das Captcha-Widget muss im Template des zugehörigen Formulars eingebunden sein. Mehr dazu [hier](https://websale.atlassian.net/wiki/x/AwAhdw).

<Info>
  Wird eine Aktion über einen Bestätigungslink per E-Mail ausgeführt (Opt-In-Link), findet keine Captcha-Prüfung statt. In diesem Fall gilt der Link selbst als Nachweis, dass ein Mensch gehandelt hat.
</Info>

### Ausführung über Links

Aktionen ohne Benutzereingaben, zum Beispiel das Ausloggen oder das Entfernen eines Artikels aus dem Warenkorb, können über einen Link ausgelöst werden, ohne das ein Formular nötig ist.

Dazu wird mit [\$wsActions.url()](/frontend/referenz/module/wsactions#\$wsactions-url) eine URL erzeugt. Die Methode erwartet drei Angaben: den Aktionsnamen, die Zielseite nach der Ausführung und optionale Parameter als Liste. Sind keine optionalen Parameter nötig, wird eine leere Liste `{}` übergeben:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<a href="{{= $wsActions.url('Logout', $wsViews.viewUrl('home.htm'), {}) }}">Ausloggen</a>
```

### Ausführung per AJAX

Standardmäßig wird nach dem Absenden eines Formulars die gesamte Seite neu geladen. Manchmal ist das aber nicht gewünscht, zum Beispiel wenn nur ein kleiner Bereich der Seite aktualisiert werden soll, ohne das der Benutzer einen sichtbaren Neuladevorgang erlebt.

In solchen Fällen kann die Aktion per AJAX ausgeführt werden. Dabei werden die Daten im Hintergrund an den Shop geschickt und die Antwort (Erfolg oder Fehler) direkt per JavaScript verarbeitet, ohne die Seite neu zu laden. CSRF-Schutz ist dabei genauso erforderlich wie bei Formularen, der Token ist über [\$wsActions.csrfToken](/frontend/referenz/module/wsactions#\$wsactions-current-csrf) abrufbar.

Ein typisches Anwendungsbeispiel:\
Der Benutzer legt ein Produkt in den Warenkorb und nur der Warenkorb-Zähler im Header aktualisiert sich, der Rest der Seite bleibt unverändert.

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
$.post("{{= $wsViews.viewUrl('ajax/actionResponse.json') }}", {
    "wscsrf":    "{{= $wsActions.csrfToken }}",
    "wsact":     "BasketItemAdd",
    "productId": "12345",
    "quantity":  2
}, function(data) {
    if (data.success) {
        // Aktion erfolgreich – z.B. Warenkorb-Zähler im Header aktualisieren
    } else {
        // Fehler anzeigen
        console.log(data.errors);
    }
});
```

### Mehrere Aktionen gleichzeitig ausführen

Manchmal sollen mit einem einzigen Klick auf “Absenden” mehrere Aktionen nacheinander ausgeführt werden. Ein typisches Beispiel ist der letzte Schritt im Checkout, bei dem die Rechnungsadresse und die Lieferadresse bestätigt und die Bestellung abgeschlossen werden.

Dafür wird statt des normalen `wsact`-Feldes das Feld `wsmultiact` verwendet, und zwar einmal pro Aktion. `wsact` und `wsmultiact` können nicht im selben Formular kombiniert werden.

Die Aktionen werden in der Reihenfolge ausgeführt in der die `wsmultiact`-Felder im Formular aufgelistet sind.\\

#### Felder einer Aktion zuordnen

Weil mehrere Aktionen im selben Formular Felder entgegennehmen, muss jedes Feld klar einer bestimmten Aktion zugeordnet werden. Das geschieht durch ein Präfix vor dem Feldnamen, getrennt durch `|`. Im Template sieht es so aus:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<input type="hidden" name="{{= $commitBillAction.id }}|addressType" value="bill">
```

Das bedeutet: Das Feld `addressType` mit dem Wert `bill` gehört zur Aktion `$commitBillAction`.\\

#### Fehler einer Aktion soll die nächste stoppen

Standardmäßig werden alle Aktionen ausgeführt, auch wenn eine davon fehlschlägt. Soll eine fehlgeschlagene Aktion die nachfolgende abbrechen, kann der Parameter `wsmultiactabortonerror` auf `on` gesetzt werden:

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

#### Fehler einer Aktion ignorieren

`wsmultiactignoreerror`  können einzelne Aktionen als unkritisch markiert werden. Schlägt eine so markierte Aktion fehl, wird das nicht als fataler Fehler behandelt. Der Parameter kann mehrfach angegeben werden, einmal pro Aktion:

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

Einen Fehler zu ignorieren wirkt sich auf zwei Situationen aus:

* **Weiterleitung trotz Fehler** \
  Standardmäßig bleibt der Nutzer bei einem Fehler auf der aktuellen Seite und wird nicht auf die in `wstarget` angegebene Zielseite weitergeleitet. Ist die fehlgeschlagene Aktion über `wsmultiactignoreerror`  markiert, findet die Weiterleitung dennoch statt.
* **Folgeaktionen laufen weiter** \
  Ist zusätzlich `wsmultiactabortonerror=on` gesetzt, würde ein Fehler normalerweise alle nachfolgenden Aktionen abbrechen. Aktionen, die über `wsmultiactignoreerror` markiert sind, lösen diesen Abbruch nicht aus - die Ausführung wird fortgesetzt.

**Beispiel: Checkout-Abschluss**\
Das folgende Beispiel zeigt den letzten Schritt eines Checkouts. Mit einem Klick auf “Jetzt bestellen” werden drei Aktionen nacheinander ausgeführt:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $commitBillAction     = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ var $commitShippingAction = $wsActions.create("CheckoutCommitDraftAddress:shipping") }}
{{ var $checkoutConfirm      = $wsActions.create("CheckoutConfirm") }}

<form method="POST" action="{{= $wsViews.current.url() }}">
  <input type="hidden" name="wscsrf"     value="{{= $commitBillAction.csrf }}">
  <input type="hidden" name="wsmultiact" value="{{= $commitBillAction.id }}">
  <input type="hidden" name="wsmultiact" value="{{= $commitShippingAction.id }}">
  <input type="hidden" name="wsmultiact" value="{{= $checkoutConfirm.id }}">
  <input type="hidden" name="wstarget"   value="{{= $wsViews.viewUrl('order-confirmation.htm') }}">
  <input type="hidden" name="{{= $commitBillAction.id }}|addressType"     value="bill">
  <input type="hidden" name="{{= $commitShippingAction.id }}|addressType" value="shipping">
  <button type="submit">Jetzt bestellen</button>
</form>
```

Ausführungsreihenfolge des Beispiels:

1. `CheckoutCommitDraftAddress:bill` - Rechnungsadresse übernehmen
2. `CheckoutCommitDraftAddress:shipping`- Lieferadresse übernehmen
3. `CheckoutConfirm` - Bestellung abschließen

### Ergebnis der Ausführung

#### Erfolg

War die Aktion erfolgreich, ist `$myAction.success` gleich `true`. In diesem Fall kann eine Erfolgsmeldung angezeigt oder der Benutzer über `wstarget` auf eine andere Seite weitergeleitet werden.

#### Fehler

Schlägt die Aktion fehl, zum Beispiel weil ein Pflichtfeld fehlt oder eine E-Mail-Adresse ungültig ist, ist `$myAction.error` gleich `true`. Die Fehlermeldungen sollten im Template ausgegeben werden, damit der Benutzer weiß, was korrigiert werden muss:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $myAction.error }}
  <div class="alert alert-danger">
    Bitte korrigiere folgende Angaben:
    <ul>
      {{ foreach $error in $myAction.errors }}
        {{ if $error.text }}
          <li>{{= $error.text }} ({{= $error.field }}){{ if $error.subCode }} – {{= $error.subCode }}{{ /if }}</li>
        {{ else }}
          <li>{{= $error.code }} ({{= $error.field }}){{ if $error.subCode }} – {{= $error.subCode }}{{ /if }}</li>
        {{ /if }}
      {{ /foreach }}
    </ul>
  </div>
{{ /if }}
```

Welche Fehlercodes eine bestimmte Aktion zurückgeben kann, ist in der jeweiligen Aktionsdokumentation ausgeführt. Eine Erklärung aller Fehlereigenschaften findet sich in der [\$wsActions Modulreferenz](/frontend/referenz/module/wsactions).

### Weiterleitung

Nach einer erfolgreich ausgeführten Aktion kann der Benutzer auf eine Zielseite weitergeleitet werden. Das verhindert außerdem, dass ein Seiten-Reload das Formular erneut absendet. Mehr dazu [hier](#2-aktionen-vorbereiten).

***

## Aktionsübersicht

Eine vollständige Übersicht aller verfügbaren Aktionen findet sich in den jeweiligen Themenbereichen:

* [Account](/frontend/referenz/aktionen/account)
* [Basket](/frontend/referenz/aktionen/basket)
* [Checkout](/frontend/referenz/aktionen/checkout)
* [Consent](/frontend/referenz/aktionen/consent)
* [DirectOrder](/frontend/referenz/aktionen/directorder)
* [Inquiry](/frontend/referenz/aktionen/inquiry)
* [Inventory](/frontend/referenz/aktionen/inventory)
* [Newsletter](/frontend/referenz/aktionen/newsletter)
* [ProductRating](/frontend/referenz/aktionen/productrating)
* [Session](/frontend/referenz/aktionen/session)
* [Stores](/frontend/referenz/aktionen/stores)
* [TestMode](/frontend/referenz/aktionen/testmode)
* [Voucher](/frontend/referenz/aktionen/voucher)
* [WatchList](/frontend/referenz/aktionen/watchlist)
