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

# $wsForm - Formulare

> Formularstrukturen laden, Formulare rendern und die übermittelten Daten eines abgeschickten Formulars im Frontend lesen – Kontakt, Frage, Inquiry.

Mit dem `$wsForm`-Modul arbeiten Sie im Frontend mit Formularen. Sie laden die Struktur eines Formulars (Felder, Labels, Validierungen), um es auszugeben, und lesen nach dem Absenden die übermittelten Daten.

Auf dieser Seite geht es um das Laden und Lesen von Formulardaten. Das Absenden selbst (und weitere Formular-Aktionen) ist unter [Aktionen → Inquiry](/frontend/referenz/aktionen/inquiry) dokumentiert; die Formulare werden in der [inquiry-Konfiguration](/konfiguration/inquiry-formulare) angelegt.

***

## Grundkonzept

Ein Formular durchläuft vier Schritte, die `$wsForm` zusammen mit der `InquirySend`-Aktion abbildet:

1. **Struktur laden** – [`loadType(formId)`](#wsform-loadtype) liefert die Felder eines Formulars (z. B. `"contact"`), damit Sie es im Frontend ausgeben können.
2. **Absenden** – der Kunde sendet das Formular über die Aktion `InquirySend` ([\$wsActions](/frontend/referenz/module/wsactions)). Das Formular schickt das versteckte Feld `formId` mit dem Formularnamen mit. Die Formularfelder werden mit dem Präfix `form.` benannt (z. B. `form.subject`).
3. **Anfrage-ID erhalten** – nach erfolgreichem Absenden liegt die Anfrage-ID vor (in `InquirySend.successInfo.inquiryId`, ebenso in [`$wsForm.inquiryId`](#wsform-inquiryid)).
4. **Daten lesen** – [`load(inquiryId)`](#wsform-load) liefert die übermittelten Daten zur Anfrage-ID, z. B. für eine Bestätigungsanzeige.

Zusätzlich listet [`loadAllTypes()`](#wsform-loadalltypes) alle Formulartypen des Shops auf.

***

## Modulübersicht

**Beispiel / Ausschnitt über** `$wsForm`

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

**JSON-Ausgabe**

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "inquiryId": "...",
  "load": "ƒ()",
  "loadAllTypes": "ƒ()",
  "loadType": "ƒ()"
}
```

Anmerkung: `"ƒ()"` kennzeichnet eine Funktion.

**Variablen in der Übersicht**

| **Variable** | **Typ** | **Beschreibung**                                        |
| ------------ | ------- | ------------------------------------------------------- |
| `inquiryId`  | string  | Anfrage-ID nach erfolgreichem Absenden eines Formulars. |

**Methoden in der Übersicht**

| **Methode**      | **Rückgabe-Typ** | **Beschreibung**                                             |
| ---------------- | ---------------- | ------------------------------------------------------------ |
| `loadType()`     | map              | Lädt die Struktur eines Formulars anhand des Formularnamens. |
| `loadAllTypes()` | array            | Lädt alle verfügbaren Formulartypen des Shops.               |
| `load()`         | map              | Lädt die übermittelten Daten einer abgeschickten Anfrage.    |

***

## Templates

Formulare werden überall im Shop verwendet, beispielsweise im Kontaktformular, beim Widerrufsformular oder bei der Passwort-Wiederherstellung.

***

## Variablen

### \$wsForm.inquiryId

Enthält die eindeutige Anfrage-ID nach dem erfolgreichen Absenden eines Formulars. Mit dieser ID rufen Sie die übermittelten Daten über [`load()`](#wsform-load) ab.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Anfrage-ID: {{= $wsForm.inquiryId }}
```

***

## Methoden

### \$wsForm.loadType()

Lädt die Struktur eines Formulars (Felder, Labels, Validierungen) anhand des Formularnamens. Nutzen Sie die zurückgegebenen Felder, um das Formular zu rendern.

**Signatur**\
`$wsForm.loadType(formId)`

**Rückgabe**\
**Rückgabe**\
`map` mit den Formular-Eigenschaften: `name` (Formularname), `fields` (Feldliste), `email` (E-Mail-Konfiguration des Formulars), `loadField` (Methode zum Laden eines einzelnen Feldes) und `nodeId` (ID des Konfigurationsknotens, als zweiter Parameter für [`$wsOptions.get(name, nodeId)`](/frontend/referenz/module/ws-options-template-optionen)).

**Parameter**

| **Name** | **Typ** | **Pflicht** | **Beschreibung**                        |
| -------- | ------- | ----------- | --------------------------------------- |
| `formId` | string  | ja          | Name des Formulars (z. B. `"contact"`). |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $field in $wsForm.loadType("contact").fields }}
  {{= $field.label }} ({{= $field.name }}){{ if $field.required }} *{{ /if }}
{{ /foreach }}
```

#### Eigenschaften eines Feld-Objekts

Ist dem Formular ein [RuleSet](https://dokumentation.websale.de/konfiguration/inquiry-formulare#inquiry-ruleset-regelbasierte-feldsteuerung) zugewiesen, werden `label`, `required`, `visible` und `defaultValue` automatisch durch dessen Regeln angepasst.

| **Eigenschaft** | **Rückgabe-Typ** | **Beschreibung**                                             |
| --------------- | ---------------- | ------------------------------------------------------------ |
| `name`          | string           | Technischer Feldname.                                        |
| `label`         | string           | Anzeigename des Feldes.                                      |
| `required`      | bool             | Pflichtfeldkennzeichen.                                      |
| `validations`   | array            | Validierungsregeln des Feldes (je `type` und `name`).        |
| `defaultValue`  | string           | Standardwert; zum Vorbelegen, wenn der Wert leer ist.        |
| `value`         | string           | Aktueller Wert (wird bei der Aktion `inquiryCheck` befüllt). |
| `visible`       | bool             | Ob das Feld angezeigt werden soll.                           |

### \$wsForm.loadAllTypes()

Lädt alle verfügbaren Formulartypen des Shops.

**Signatur**\
`$wsForm.loadAllTypes()`

**Rückgabe**\
`array` – Liste aller Formulartypen.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $formType in $wsForm.loadAllTypes() }}
  Formular: {{= $formType.name }}
{{ /foreach }}
```

### \$wsForm.load()

Lädt die übermittelten Daten einer abgeschickten Formularanfrage. Übergeben Sie die Anfrage-ID, die Sie nach dem Absenden erhalten haben.

**Signatur**\
`$wsForm.load(inquiryId)`

**Rückgabe**\
`map` – die Anfragedaten (Struktur siehe unten).

**Parameter**

| **Name**    | **Typ** | **Pflicht** | **Beschreibung**              |
| ----------- | ------- | ----------- | ----------------------------- |
| `inquiryId` | string  | ja          | ID der abgeschickten Anfrage. |

#### Struktur der Anfragedaten

| **Eigenschaft** | **Rückgabe-Typ** | **Beschreibung**                                         |
| --------------- | ---------------- | -------------------------------------------------------- |
| `id`            | string           | Eindeutige ID der Anfrage.                               |
| `formId`        | string           | Name des verwendeten Formulars.                          |
| `createdAt`     | string           | Zeitpunkt des Absendens (ISO 8601, UTC).                 |
| `submitter`     | map              | Daten des Absenders (`email`, `sessionId`, `ipAddress`). |
| `form`          | map              | Eingegebene Felddaten, je Feld `{ label, value }`.       |

<Info>
  Auf ein einzelnes Feld greifen Sie über seinen technischen Namen zu, z. B. `form.firstName.value` und `form.firstName.label`.
</Info>

***

## Aktionen

Aktionen zu diesem Modul (Absenden, Prüfen) sind separat dokumentiert: [Aktionen → Inquiry](/frontend/referenz/aktionen/inquiry).

***

## Beispiele

### Formularfelder rendern

`loadType()` liefert die Felder eines Formulars, aus denen Sie die Eingabefelder erstellen. Die Feldnamen erhalten das Präfix `form.`. Ausgeblendete Felder (`visible = false`) überspringen Sie und Pflichtfelder kennzeichnen Sie mit required.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $field in $wsForm.loadType("contact").fields }}
  {{ if $field.visible }}
    <label>
      {{= $field.label }}{{ if $field.required }} *{{ /if }}
      <input type="text" name="form.{{= $field.name }}" value="{{= $field.defaultValue }}">
    </label>
  {{ /if }}
{{ /foreach }}
```

**Ergebnis** \
Für jedes sichtbare Feld des Kontaktformulars gibt es ein beschriftetes Eingabefeld mit dem Präfix `form-`. Pflichtfelder sind mit einem Sternchen (\*) markiert. Das Absenderfeld `email` ist kein `loadType`-Feld und wird separat als `input name="email"` ergänzt.

### Vollständiges Kontaktformular mit Absenden und Bestätigung

Dieses Beispiel zeigt den kompletten Loop: Formular mit den nötigen versteckten Feldern und `form.`-Präfix rendern, bei Fehler die Eingaben erhalten und Feldfehler anzeigen, bei Erfolg die Daten über `load()` lesen.

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

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

  {{ if $action.success }}
    {{ var $inquiry = $wsForm.load($action.successInfo.inquiryId) }}
    <p>Danke für Ihre Anfrage (ID {{= $inquiry.id }}).</p>
    <p>Bestätigung an: {{= $inquiry.submitter.email }}</p>
  {{ else }}
    <input type="email" name="email" placeholder="E-Mail"
           value="{{= $action.params.email | ifNull('') }}">

    <input type="text" name="form.subject" placeholder="Betreff"
           value="{{= $action.params.form.subject | ifNull('') }}">
    {{ if $action.errorsByField.subject }}
      <span class="error">{{= $action.errorsByField.subject[0].text }}</span>
    {{ /if }}

    <textarea name="form.comment" placeholder="Ihre Nachricht">{{= $action.params.form.comment | ifNull('') }}</textarea>
    {{ if $action.errorsByField.comment }}
      <span class="error">{{= $action.errorsByField.comment[0].text }}</span>
    {{ /if }}

    <button type="submit">Absenden</button>
  {{ /if }}
</form>
```

**Ergebnis** \
Das Formular erscheint vor dem Absenden. Bei fehlerhafter Eingabe bleiben die Werte erhalten und die Feldfehler werden angezeigt. Nach erfolgreichem Absenden erscheint die Bestätigung mit der Anfrage-ID.

<Note>
  Nutzt das Formular ein Captcha (z. B. reCAPTCHA v3), gehört es hinter `{{ if $wsConsent.checkAllowed("recaptchav3") }}` und braucht ein Feld `<input type="hidden" name="wscaptchatoken">` sowie die Captcha-Komponente. Siehe [\$wsConsent](/frontend/referenz/module/wsconsent).
</Note>

Beispiel einer von `load()` zurückgegebenen Struktur (Felder gemäß dem echten Kontaktformular; die `load()`-Struktur selbst ist noch zu bestätigen):

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "id": "52ad06427c68738c",
  "formId": "contact",
  "createdAt": "2025-04-14T06:43:57Z",
  "submitter": {
    "email": "kundin@beispiel.de",
    "ipAddress": "95.90.217.XXX",
    "sessionId": "c5a37018627bf18e…"
  },
  "form": {
    "subject": { "label": "Betreff", "value": "Test-Anfrage" },
    "comment": { "label": "Ihre Nachricht", "value": "Bitte um weitere Infos" }
  }
}
```

***

## Weiterführende Links

* [Aktionen → Inquiry](/frontend/referenz/aktionen/inquiry) – das Absenden und Prüfen von Formularen (`InquirySend`, `inquiryCheck`).
* [inquiry - Formulare](/konfiguration/inquiry-formulare) – legt die Formulare und Felder an, inkl. RuleSet.
* [actions - Formulare](/konfiguration/actions-fehlertexte-e-mails/actions-formulare) – Konfiguration der Formular-Aktionen.
