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

# ws-filter

> ws-filter rendert einen einzelnen Filter (Checkbox, Range, Slider, Bild, Label) für Eigenschaften wie Farbe, Preis oder Verfügbarkeit und steuert dessen Werte.

Die WebComponent `<ws-filter>` ermöglicht die Filterung der Suchergebnisse oder Kategorien basierend auf verschiedenen Produkteigenschaften. Sie unterstützt verschiedene Filtertypen wie Checkboxen, Wertebereiche (Range), Schieberegler (Slider), bildbasierte Auswahl (Image) und klickbare Labels (Label).

Es werden dynamisch generierte Filter (z. B. Farben) sowie individuell definierte Custom-Filter (z. B. Topseller, Verfügbarkeit) unterstützt.

***

## Voraussetzung

* Die Komponente muss innerhalb von `<ws-filters>` eingebunden werden
* Damit die Filterkomponente korrekt funktioniert, muss das Attribut `name=""` den technischen Spaltennamen aus dem Datenfeed enthalten, dieser muss zwingend lowercase (kleingeschrieben) sein. Dieser Spaltenname gibt an, auf welches Produktdatenfeld sich der Filter beziehen soll. Beispiele für mögliche Spaltennamen sind:
  * `price`: Für Preisfilter.
  * `color`: Für Farbauswahlfilter.
  * `brand`: Für Markenfilter.
* Die Spaltennamen im Datenfeed werden über die Datenfelder definiert, die in der Konfiguration des [Such-Moduls](/ws-search/konfiguration-des-such-moduls) aktiviert und für Filter, Sortierung oder Suche verwendet werden.

***

## Dynamische und Custom-Filter

Die Komponente `<ws-filter>` unterstützt zwei Arten von Filtern: **dynamische Filter** und **Custom-Filter**. Beide Filterarten können im Frontend gleich aussehen (z. B. als Checkbox).

### Dynamische Filter

Dynamische Filter basieren direkt auf den Produktdaten – also auf Informationen, die im Datenfeed zu jedem einzelnen Produkt verfügbar sind. Typische Beispiele sind Farbe, Größe oder Marke.

Typische Einsatzbereiche für dynamische Filter:

* Farbe (`color`)
* Größe (`size`)
* Marke (`brand`)
* Preis (`price`)
* Zutaten (`ingredients`)

### Custom-Filter

Custom-Filter basieren nicht auf den einzelnen Werten im Feed, sondern auf technisch definierten Filterbedingungen (z. B. „Lagerbestand ≥ 1"). Custom-Filter sind somit vordefinierte Filter, bei denen Sie entscheiden, was genau gefiltert werden soll.

Typische Anwendungsfälle:

* Nur verfügbare Produkte (z. B. Lagerbestand > 0)
* „Neuheiten" basierend auf dem Creation Date
* Sale-Produkte (z. B. `is_reduced = true`)
* Bewertung (z. B. `rating >= 4`)

***

## Komponente für Filter

Die einzelnen `<ws-filter>` für die Filter-Elemente müssen immer innerhalb von `<ws-filters>` liegen.

Ist `<ws-filters>` bereits vorhanden, können die weiteren Filter einfach dort ergänzt werden.

### Komponente für dynamische Filter

Die Komponente kann wie folgt auf der Kategorie- und Suchergebnisseite eingebunden werden:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...

  <ws-filter type="checkbox" multiple="true" name="color"></ws-filter>
  <ws-filter type="checkbox" multiple="true" name="size"></ws-filter>
  <ws-filter type="checkbox" multiple="true" name="brand"></ws-filter>
  ...

  <ws-filter type="range" display-type="slider-fields" name="price"></ws-filter>
  ...

  <ws-filter type="checkbox" multiple="true" name="ingredients" negate></ws-filter>
  ...

  <ws-filter type="checkbox" multiple="true" name="ingredients" negate></ws-filter>
  <ws-filter type="checkbox" multiple="true" name="neq_ingredients" negate></ws-filter>
  ...
</ws-filters>
```

* **Attribute**
  * `type`: Gibt den Filtertyp an.
    * `checkbox`: Auswahl über Checkboxen (z. B. Kategorien oder Farben)
      * `negate`: Aktiviert den Ausschluss-Filter. Produkte, die die gewählten Filterwerte enthalten, werden nicht angezeigt. Nur bei `type="checkbox"` verfügbar
    * `range`: Schieberegler für Wertebereiche (z. B. Preis).
      * `display-type`: Darstellungstyp des Range-Filters
        * `slider`: Stellt den Range-Filter nur als einen Slider dar
        * `fields`: Stellt den Range-Filter nur als Number-Input-Felder dar (2 Input-Felder)
        * `slider-fields`: Stellt den Range-Filter als Slider und Number-Input-Felder dar
    * `image`: Bildbasierte Auswahl über anklickbare Bilder (z. B. Farben, Materialien, Muster). Details siehe [Bildbasierte Filter](#bildbasierte-filter-type-image).
    * `label`: Klickbare Label-Optionen mit verstecktem Checkbox-Input (z. B. Größen). Details siehe [Label-Filter](#label-filter-type-label).
  * `multiple="true"`: Erlaubt die Mehrfachauswahl (für `type="checkbox"`, `type="image"` und `type="label"`; Default bei `image` und `label`: `false`).
  * `use-numeric-sort`: Numerisch sortieren. Mögliche Werte: `true`
  * `name`: Definiert das Produktdatenfeld, auf das der Filter angewendet wird, z.B.
    * `catids` für Kategorien
    * `price` für Preis

<Info>
  Produktdatenfelder, die als Filter genutzt werden, werden standardmäßig positiv ausgewertet; soll ein Feld alternativ oder ausschließlich negativ filtern, ist in der Konfiguration die negative Variante zu aktivieren. Die Logik steuert das Attribut `negate` innerhalb von `<ws-filters>`. Sollen beide Varianten parallel verfügbar sein, ist für die negative Darstellung der technische Feldname mit dem Präfix `neq_` (z.B. `neq_field_name`) zu verwenden; bei ausschließlich negativer Nutzung ist kein separates `neq_`-Feld erforderlich. Wichtig: Damit das `neq_`-Feld überhaupt existiert, muss das `negate`-Attribut zusätzlich im [Importmodul](/ws-search/konfiguration-des-such-moduls) gesetzt werden.

  Soll der Nutzer selbst zwischen Include und Exclude umschalten können, steht dafür die Komponente [ws-filter-toggle](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filter-toggle) zur Verfügung.
</Info>

### Komponente für Custom-Filter

Die einzelnen `<ws-filter>` für die Filter-Elemente müssen immer innerhalb von `<ws-filters>` liegen.

Die Komponente kann wie folgt auf der Kategorie- und Suchergebnisseite eingebunden werden:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...
    <ws-filter type="checkbox" display-style="hide" name="salesrank" static-label="Nur Topseller"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="rating" static-label="Nur top-bewertete Produkte"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="new_field" static-label="Nur die neusten Produkte"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="inventory" static-label="Nur verfügbare Produkte"></ws-filter>
    <ws-filter type="checkbox" display-style="hide" name="reduced_field" static-label="Nur reduzierte Produkte"></ws-filter>
  ...
</ws-filters>
```

* **Attribute**
  * `type`: Gibt den Filtertyp an.
    * `checkbox`: Auswahl über Checkboxen (z. B. Kategorien oder Farben)
      * `negate`: Aktiviert den Ausschluss-Filter. Produkte, die die gewählten Filterwerte enthalten, werden nicht angezeigt. Nur bei `type="checkbox"` verfügbar
  * `name`: Definiert das Produktdatenfeld, auf das der Filter angewendet wird, z.B.
    * `catids` für Kategorien
    * `price` für Preis
  * `disable-style`: Gibt an, wie sich der Filter verhalten soll, wenn er keine Werte enthält:
    * `hide`: Filter verschwindet grafisch
    * `inactive`: Filter ist einfach nur inaktiv → reagiert nicht
    * `gray-out`: Filter wird ausgegraut und ist inaktiv
    * `line-through`: Filter wird durchgestrichen und ist inaktiv
    * `blur`: Filter wird geblurred (2px) und ist inaktiv
    * `disable-style="disable-style"`: Abseits der vordefinierten Styles kann man auch die Klasse `disable-style` anlegen und diese in der eigenen CSS-Datei entsprechend mit Anweisungen belegen.
  * `static-label`: Optionaler Label-Text zur Anzeige eines benutzerdefinierten Textes für einen Custom-Filter

<Info>
  `<ws-filter>`-Instanzen müssen immer innerhalb von `<ws-filters>` platziert werden. Ist `<ws-filters>` bereits vorhanden, können die Custom-Filter dort ergänzt werden.
</Info>

### Bildbasierte Filter (`type="image"`)

Mit `type="image"` werden Filteroptionen als anklickbare Bilder dargestellt - z. B. für Farben, Materialien oder Muster.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filter
  type="image"
  name="color"
  image-path="/images/colorpick/"
  image-format="jpg"
  label-class="color-swatch"
  multiple="true">
</ws-filter>
```

* **Attribute**
  * `image-path`: **Pflichtfeld.** Pfad zum Verzeichnis, in dem die Bilder der Filteroptionen liegen.
  * `image-format`: Datei-Endung der Bilder. Default: `jpg`
  * `image-map`: JSON-Mapping von Filterwert zu Dateiname - für Bildnamen, die von der automatischen Namens-Normalisierung abweichen.
  * `label-class`: CSS-Klasse für das Label-Element.
  * `multiple`: Erlaubt die Mehrfachauswahl. Default: `false`

**Bildnamen-Konvention**

Die Dateinamen werden automatisch aus den Filterwerten abgeleitet. Dabei werden die Werte normalisiert:

* Kleinbuchstaben
* Leerzeichen werden zu Unterstrichen

Beispiel: Der Wert `Dark Blue` wird zur Datei `dark_blue.jpg`. Weicht ein Bildname von dieser Konvention ab, kann die Zuordnung über `image-map` definiert werden.

**Verhalten**

* Das Label der Filteroption zeigt das Bild als Hintergrundbild (`background-image`).
* Ein Tooltip zeigt den Original-Wert der Option an.
* Ausgewählte Optionen erhalten die CSS-Klasse `.checked` am Label.
* Fehlt ein Bild, wird als Fallback der Text der Option angezeigt.

### Label-Filter (`type="label"`)

Mit `type="label"` werden Filteroptionen als klickbare Labels mit verstecktem Checkbox-Input dargestellt - z. B. für Größen, die als Buttons statt als Checkbox-Liste angeboten werden sollen.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filter
  type="label"
  name="size"
  label-class="size-class"
  data-template="{% value %} ({% count %})"
  multiple="true">
</ws-filter>
```

* **Attribute**
  * `label-map`: JSON-Mapping von Filterwert zu Anzeige-Label (z. B. `{"xl": "Extra Large"}`) - für Anzeigetexte, die vom technischen Wert abweichen.
  * `data-template`: Mustache-Template für den Label-Inhalt (z. B. `{% value %} ({% count %})` für den Wert mit Trefferanzahl).
  * `label-class`: CSS-Klasse für das Label-Element.
  * `multiple`: Erlaubt die Mehrfachauswahl. Default: `false`

**Verhalten**

* Der Checkbox-Input wird versteckt gerendert; die Auswahl erfolgt über das klickbare Label.
* Ausgewählte Optionen erhalten die CSS-Klasse `.active` am Label.

### Sortierung der Filterwerte innerhalb eines Filters (benutzerdefinierte Reihenfolge)

Standardmäßig werden Filterwerte alphabetisch sortiert (z. B. „Adult, Junior, Senior"), was für fachliche Reihenfolgen (z. B. „Junior, Adult, Senior" oder Größen S, M, L, XL, XXL) ungeeignet ist.

Dafür kann zum Beispiel pro Filter eine Sortierliste bereitgestellt werden, die per Javascript im Template hinterlegt wird.

#### Statische Sortierliste (manuell gepflegt)

Der Filter „Lebensphase" enthält die Werte Adult, Junior und Senior, die aber in folgender Reihenfolge sortiert werden sollen: Junior - Adult - Senior.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...
  <ws-filter type="checkbox" multiple="true" name="lebensphase"></ws-filter>
  ...
</ws-filters>
```

Die Sortierung wird über das Script realisiert:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script type="text/plain" id="sort-list-lebensphase">
  ['Junior','Adult','Senior']
</script>
```

* **Attribute**
  * `sort-list-` = technischer Name des Produktdatenfelds/Filters, immer lowercase (z. B. `lebensphase`)
  * Kommen neue Werte hinzu, muss die Liste manuell erweitert werden.

#### Sortierliste aus dem Import (Wawi/ERP)

Der Filter „Lebensphase" enthält die Werte Adult, Junior und Senior, die aber in folgender Reihenfolge sortiert werden sollen: Junior - Adult - Senior.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filters>
  ...
  <ws-filter type="checkbox" multiple="true" name="lebensphase"></ws-filter>
  ...
</ws-filters>
```

Die Sortierung wird über ein Javascript realisiert, das über das Tag `WS-FilterSortList()` auf eine über den Import bereitgestellte Sortierungsliste zugreift:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script type="text/plain" id="sort-list-lebensphase">
  ['Junior','Adult','Senior']
</script>
```

* **Attribute**
  * `WS-FilterSortList(Feldname)` ist case-sensitive → Feldname muss genau wie im Original verwendet werden (z. B. `Lebensphase`).
  * In der Script-ID bleibt `sort-list-` trotzdem **lowercase** (`sort-list-lebensphase`)
  * Die Bereitstellung dieser Importliste muss mit Wawi/ERP abgestimmt werden.

### Sichtbarkeit von dynamischen und Custom-Filtern (Ausblenden)

Die Steuerung, ob ein Filter sichtbar ist, erfolgt über das Attribut `filter-container`, welches HTML-Elementen zugewiesen werden muss.

Mehr Informationen dazu siehe [ws-filters](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filters).

***

## HTML & CSS

### CSS & Styling für Checkboxen

Die Komponente mit dem Attribut `type="checkbox"` generiert keine spezifischen CSS-Klassen.

Innerhalb der Komponente können keine zusätzlichen CSS-Anweisungen oder HTML-Elemente eingebunden werden.

HTML-Elemente und zusätzliche CSS-Stile können jedoch um die Komponente herum ergänzt werden, um das Layout flexibel anzupassen.

Die Komponente erzeugt zum Beispiel für `type="checkbox"` den folgenden Quellcode:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<input type="checkbox" value="blau" id="farbgrp-blau" name="farbgrp">
<label for="farbgrp-blau">blau</label>

<input type="checkbox" value="rot" id="farbgrp-rot" name="farbgrp">
<label for="farbgrp-rot">rot</label>
```

### CSS & Styling für Image-Filter

Beim Filtertyp `image` wird das Bild als `background-image` am Label gesetzt; das Label selbst kann über das Attribut `label-class` mit einer eigenen CSS-Klasse gestaltet werden (z. B. Größe und Zuschnitt des Bildes). Ausgewählte Optionen tragen zusätzlich die Klasse `.checked` und können darüber markiert werden (z. B. Rahmen oder Haken-Overlay).

### CSS & Styling für Label-Filter

Beim Filtertyp `label` wird der Checkbox-Input versteckt; sichtbar ist nur das Label, das über das Attribut `label-class` mit einer eigenen CSS-Klasse gestaltet werden kann (z. B. als Button). Ausgewählte Optionen tragen zusätzlich die Klasse `.active` und können darüber hervorgehoben werden.

### CSS & Styling für Range-Slider

Für die Range-Slider wird [noUiSlider](https://refreshless.com/nouislider/) verwendet – eine JavaScript-Bibliothek, die benutzerfreundliche Schieberegler bereitstellt:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.0/nouislider.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.0/nouislider.min.js"></script>
```

Für `type="range"` wird zum Beispiel folgender Quellcode erzeugt:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<ws-filter type="range" display-type="slider-fields" name="price">

  2.00

  4000.00

  <style class="slider-tooltip-style">
    .noUi-tooltip {
      display: none;
    }
  </style>
  <input type="number" name="price-min" class="range-field" min="2" max="3999" step="1"
      value="2"><input type="number" name="price-max" class="range-field" min="3" max="4000" step="1" value="4000">

</ws-filter>
```

Funktionen von `noUiSlider`:

* Dynamische Bereichsauswahl mit zwei Griffen (z. B. Preisfilter von 0 bis 259 €)
* Anzeige von Tooltips mit den aktuellen Werten
* Anpassbares Styling über CSS

Die folgenden Klassen werden in der Ausgabe erzeugt und können für individuelles Styling verwendet werden:

* `noUi-base`: Basis-Container des Sliders
* `noUi-connect`: Bereich zwischen den beiden Griffen des Sliders (zeigt den ausgewählten Bereich)
* `noUi-origin`: Position des jeweiligen Slider-Griffs
* `noUi-tooltip`: Tooltip, der den aktuellen Wert des Griffs anzeigt
* `noUi-handle`: Der tatsächliche Griff, der bewegt werden kann

Die [noUiSlider-Bibliothek](https://refreshless.com/nouislider/) sollte heruntergeladen werden und kann dann entweder direkt oder über das [WEBSALE PageSpeed Tool](https://doku.websale.net/guide_jsjq.html#1einbindenneuerjavascript-dateienundnutzungdesminify-tools) eingebunden werden.

### Javascript-Workaround für die Anzeige des Währungssymbols in einer Price-Range

Die Funktion muss selbstverständlich bei der Auswahl des Filters ausgeführt werden und zum Beispiel auch, wenn Artikel geladen werden.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script>
...
function wsPriceFilterCurrency() {
  var currencySymbol = document.createElement("span");
      currencySymbol.innerHTML = "~WS-CurrencySymbol~";
      currencySymbol = currencySymbol.innerText;
      var priceInputs = document.querySelectorAll("ws-filter[name='price'] input[type='number']");
      priceInputs.forEach(function(input) {
        var wrapper = input.closest(".range-field-wrapper");
        if (!wrapper) return;
        // Neue Struktur bauen
        var inputGroup = document.createElement("div");
        inputGroup.className = "wsPriceFilterGroup";
        var prepend = document.createElement("div");
        prepend.className = "wsPriceFilterCurrency";
        prepend.textContent = currencySymbol;
        // Input aus DOM entfernen und in neue Struktur einfügen
        input.parentNode.removeChild(input);
        inputGroup.appendChild(prepend);
        inputGroup.appendChild(input);
        // Neue Struktur anstelle des ursprünglichen Inputs einfügen
        wrapper.appendChild(inputGroup);
      });
    }
 ...
 </script>
```

***

## URL-Filterparameter

Filter können über die URL direkt an das Suchmodul übergeben werden – z. B. für Kampagnen, Vorauswahlen oder direkte Verlinkungen mit aktivierten Filtern.

Mehr dazu in der Dokumentation zu [URL-Filterparameter](/ws-search/integration-in-die-templates-storefront/webcomponents/url-filterparameter-query-parameter).


## Related topics

- [ws-filters](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filters.md)
- [ws-filter-toggle](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filter-toggle.md)
- [ws-filter-chip](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filter-chip.md)
- [ws-filter-reset](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-filter-reset.md)
- [ws-search](/ws-search/integration-in-die-templates-storefront/webcomponents/ui-komponenten/ws-search.md)
