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

# Cart items-Block

> Der Cart items-Block: die Positionsliste, die Product-Zeile und der Container für verschachtelte Unterblöcke.

> Der **Cart items**-Block ist die Liste der Positionen im Cart. Er rendert jedes vom Kunden hinzugefügte Produkt mit Bild, Titel, Variante, Preis, Mengenwähler und Entfernen-Steuerung. Er ist ein Pflichtblock und der Container, der die Unterblöcke des Carts beherbergt (die **Product**-Zeile, [**Subscription upgrade**](/de/aftersell/cart/subscription-upgrade-block) und [**Custom code**](/de/aftersell/cart/custom-code-blocks)). Er bietet die Struktur, an der sich zeilenbasierte Unterblöcke anheften.

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-items-block-line-product-title-variant.png?fit=max&auto=format&n=1Y3gBpUfxv16VGSW&q=85&s=3c9f088b55cfd8450dcb8670dfe0728a" alt="Cart items-Block mit Positionen samt Produktbild, Titel, Variante, Preis, Mengenwähler und Entfernen-Steuerung" width="1420" height="486" data-path="images/aftersell/cart-items-block-line-product-title-variant.png" />
</Frame>

<div id="the-product-row">
  ## Die Product-Zeile
</div>

Innerhalb von Cart items sitzt der **Product**-Unterblock: die eigentliche Positionszeile. Sie ist gesperrt und wird automatisch hinzugefügt, sodass jeder Cart items-Block immer genau eine Product-Zeile hat, die du nicht entfernen kannst; andere Unterblöcke positionierst du um sie herum. Ihre Einstellungen steuern, wie die Preise jeder Zeile angezeigt werden:

| Einstellung                                | Was sie steuert                                                                                                                                                                                                                                                                                                                                              | Standard                                                         |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| **Strike-through price**                   | Welcher Preis durchgestrichen angezeigt wird: **Compare-at oder Vorab-Rabattpreis, je nachdem, welcher höher ist**, **Compare-at-Preis**, **Vorab-Rabattpreis** oder **Kein Durchstreichen**.                                                                                                                                                                | Compare-at oder Vorab-Rabattpreis, je nachdem, welcher höher ist |
| **Strike-through price for subscriptions** | Dieselbe Auswahl für Abonnementzeilen, mit zwei Unterschieden: eine zusätzliche Option **Subscription compare-at price**, und **Compare-at price** heißt hier **Product compare-at, then subscription compare-at**.                                                                                                                                          | Compare-at oder Vorab-Rabattpreis, je nachdem, welcher höher ist |
| **Savings label**                          | Ob Ersparnisse als **Amount** (Betrag), **Percentage** (Prozentsatz) angezeigt oder **Hidden** (ausgeblendet) werden.                                                                                                                                                                                                                                        | Amount                                                           |
| **Bundle price**                           | Wie der angezeigte Preis für Bundle-Zeilen berechnet wird. **Automatic** zeigt die Summe aller Artikel im Bundle (oder den Preis des Hauptartikels, wenn die anderen Artikel kostenlos sind). **Main item price only** zeigt nur den Preis des Haupt-(Anker-)Artikels. Dies ist nur eine Anzeigebeschriftung — Shopifys Warenkorbsumme ist immer maßgeblich. | Automatic                                                        |
| **Savings text**                           | Die Ersparnis-Beschriftung. Unterstützt das Token `{{value}}`.                                                                                                                                                                                                                                                                                               | `Save {{value}}`                                                 |

Die Zeile selbst rendert das Produktbild (mit Link zur Produktseite, sofern verfügbar), Titel, Variante, Preis und einen eventuell durchgestrichenen Compare-at-Preis, einen Mengenwähler und eine Entfernen-Schaltfläche. Bundle-Zeilen zeigen eine ausklappbare Liste ihrer Komponenten.

<div id="text-styling">
  ### Textgestaltung
</div>

Die Product-Zeile enthält in ihren Design-Einstellungen einen Abschnitt **Text**. Damit steuerst du die Typografie einzelner Textelemente in jeder Position. Wähle ein Textelement im Picker aus, um seine Einstellungen anzupassen:

| Einstellung        | Was sie steuert                                                                                                                                                             |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Text color**     | Farbe des ausgewählten Textelements.                                                                                                                                        |
| **Font**           | **Theme font** (übernimmt die Schrift deines Themes) oder **Custom font** (Namen einer Schrift eingeben, die dein Theme bereits lädt). Nur für **Product title** verfügbar. |
| **Size**           | Schriftgröße in Pixeln.                                                                                                                                                     |
| **Weight**         | Schriftstärke: Light, Regular, Medium, Semibold oder Bold.                                                                                                                  |
| **Line height**    | Zeilenhöhe als Multiplikator der Schriftgröße (zum Beispiel `1.4`).                                                                                                         |
| **Letter spacing** | Buchstabenabstand in Pixeln. Negative Werte engen den Text.                                                                                                                 |

Die gestaltbaren Textelemente sind nach Kategorie gruppiert:

**Product**

* **Product title** — der Produktname in jeder Zeile. Unterstützt außerdem eine benutzerdefinierte Schriftfamilie.
* **Variant** — die Variantenbezeichnung (zum Beispiel *Size: Medium*).
* **Subscription plan** — die schreibgeschützte Plan-Bezeichnung auf Abonnementzeilen.

**Pricing**

* **Price** — der aktuelle Preis der Zeile.
* **Compare-at price** — der durchgestrichene ursprüngliche Preis.
* **Savings** — die Ersparnis-Beschriftung (zum Beispiel *Save \$5.00*). Nur Größe und Zeilenhöhe — Fettschrift und Farbe werden im Rich Text Editor oberhalb festgelegt.

**Bundle**

* **Bundle toggle** — der ausklappbare Header, der die Komponentenliste eines Bundles öffnet.
* **Bundle item title** — der Titel jeder Komponente innerhalb eines Bundles.
* **Bundle item variant** — die Variantenbezeichnung für jede Bundle-Komponente.

Wenn du ein Feld leer lässt, behält das Element seinen Standardwert.

<Tip>
  Klickst du ein Textelement direkt in der Cart-Vorschau an, wird es hervorgehoben und seine Steuerungen öffnen sich automatisch im Panel.
</Tip>

<div id="discount-tags-design">
  ### Design der Rabatt-Tags
</div>

Die Product-Zeile enthält in ihren Design-Einstellungen einen Abschnitt **Discount tags**. Damit gestaltest du die Rabatt-Tag-Pills, die bei jeder Position erscheinen:

| Einstellung          | Was sie steuert                           | Standard  |
| -------------------- | ----------------------------------------- | --------- |
| **Background color** | Füllfarbe des Rabatt-Tag-Pills.           | `#F1F1F1` |
| **Text color**       | Textfarbe innerhalb des Rabatt-Tag-Pills. | `#585858` |
| **Border radius**    | Eckenrundung des Rabatt-Tag-Pills.        | `6px`     |

Diese Einstellungen gelten nur für Positions-Rabatt-Tags im Cart items-Block. Rabattcode-Tags im [Summary-Block](/de/aftersell/cart/summary-block) werden separat gestaltet.

<div id="sub-blocks-and-how-they-position">
  ## Unterblöcke und ihre Positionierung
</div>

Cart items ist der einzige Block, der Unterblöcke beherbergt. **Unterblöcke werden einmal pro Zeile gerendert, innerhalb jeder Produktzeile**, positioniert relativ zur fixierten Product-Zeile:

* Unterblöcke, die **vor** der Product-Zeile angeordnet sind, erscheinen in jeder Zeile **über** dem Produktinhalt.
* Unterblöcke, die **nach** der Product-Zeile angeordnet sind, erscheinen in jeder Zeile **unter** dem Produktinhalt.

Ein [Subscription upgrade](/de/aftersell/cart/subscription-upgrade-block), das nach der Product-Zeile platziert ist, erscheint also unter jeder infrage kommenden Zeile — nicht einmal am Ende der gesamten Liste.

<div id="behavior">
  ## Verhalten
</div>

* Wenn der Cart keine Artikel enthält, wechselt der Drawer in den leeren Zustand und dieser Block wird nicht angezeigt.
* **Es läuft immer nur eine Cart-Änderung gleichzeitig.** Während eine Mengenänderung oder Entfernung läuft, sind die Steuerelemente der Zeile deaktiviert, um den Cart konsistent zu halten, und werden wieder aktiviert, sobald die Änderung abgeschlossen ist.
* Das Absenken der Menge einer Zeile unter 1 entfernt sie. Eine Menge, die der Store ablehnt (zum Beispiel über den verfügbaren Bestand hinaus), wird auf den letzten gültigen Wert zurückgesetzt.
* **Bundles ändern sich als Einheit.** Das Anpassen der Menge auf der Ankerzeile eines Bundles skaliert das gesamte Bundle in einem Vorgang — wenn ein Kind mit 3 pro Anker enthalten ist, bringt eine Erhöhung des Ankers von 1 auf 2 dieses Kind auf 6. Das Entfernen des Ankers entfernt alle Bundle-Mitglieder auf einmal.
* **Manche Bundles lassen sich nicht in der Menge ändern.** Wenn eines der Kinder eines Bundles mit einer gebrochenen Rate enthalten ist (zum Beispiel 1,5 pro Anker), ist der Mengenwähler dieses Bundles gesperrt: Die +/−-Schaltflächen und das Mengenfeld sind beide deaktiviert, und eingetippte Mengen werden nicht akzeptiert. Das Bundle kann weiterhin entfernt werden.
* **Abonnementzeilen zeigen ihren Plan.** Wenn eine Zeile einen Selling Plan hat und der Unterblock [Subscription upgrade](/de/aftersell/cart/subscription-upgrade-block) deaktiviert oder nicht hinzugefügt ist, zeigt die Product-Zeile eine schreibgeschützte Plan-Beschriftung unter der Variante — zum Beispiel *Delivers every month (save 30%)*. Wenn dieser Unterblock aktiviert ist, präsentiert er den Plan in seiner eigenen Auswahl, sodass die schreibgeschützte Beschriftung unterdrückt statt dupliziert wird.

<div id="placement-and-limits">
  ## Platzierung und Grenzen
</div>

* **Bereich:** Body.
* **Maximum:** 1 pro Cart-Zustand.
* **Zustand:** nur gefüllter Cart.
* **Gesperrt und standardmäßig hinzugefügt.** Cart items kann nicht entfernt oder ausgeblendet, nur neu positioniert werden.

<div id="custom-template">
  ## Benutzerdefiniertes Template
</div>

Unterstützt ein [benutzerdefiniertes Template](/de/aftersell/cart/custom-templates) über seinen Code-Tab, das das integrierte Markup dieses Blocks durch dein JSX ersetzt. Dies sind die Props, die es erhält.

Der **Cart items**-Container hat kein benutzerdefiniertes Template. Die **Product**-Zeile darin schon, und sie ist die umfangreichste Oberfläche im Cart: Dein Template wird einmal pro Zeile gerendert.

<div id="line-content">
  ### Zeileninhalt
</div>

| Prop               | Typ                         | Wofür sie dient                                                                                                                                                                                                                |
| ------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `title`            | `string`                    | Produkttitel als reiner Text.                                                                                                                                                                                                  |
| `variantTitle`     | `string \| null`            | Variantenbezeichnung. `null` bei Produkten mit einer einzigen Variante und nativen Bundles.                                                                                                                                    |
| `url`              | `string \| null`            | URL der Produktseite. `null`, wenn die Zeile nicht verlinken soll.                                                                                                                                                             |
| `imageUrl`         | `string \| null`            | Zeilenbild. `null`, wenn das Produkt keines hat.                                                                                                                                                                               |
| `quantity`         | `number`                    | Aktuelle Menge der Zeile.                                                                                                                                                                                                      |
| `price`            | `string`                    | Zeilenpreis, **bereits formatiert**.                                                                                                                                                                                           |
| `compareAtPrice`   | `string \| null`            | Der durchgestrichene "Vorher"-Preis, bereits formatiert. `null`, wenn nichts durchzustreichen ist.                                                                                                                             |
| `savingsHtml`      | `string \| null`            | Ersparnis-Beschriftung als bereinigtes HTML. `null`, wenn ausgeblendet oder keine Ersparnis vorliegt.                                                                                                                          |
| `discountTags`     | `string[]`                  | Titel der Rabatte auf dieser Zeile, z. B. `['Spring Sale']`. `[]`, wenn keine vorhanden sind.                                                                                                                                  |
| `sellingPlanLabel` | `string \| null`            | Schreibgeschützter Name des Abonnementplans. `null` bei einer Einmalkauf-Zeile oder wenn der Unterblock [Subscription upgrade](/de/aftersell/cart/subscription-upgrade-block#custom-template) stattdessen die Plan-UI rendert. |
| `bundle`           | `object \| null`            | [Bundle](/de/aftersell/cart/sdk-cart-object#bundles)-View-Model auf einer Ankerzeile. Sonst `null`.                                                                                                                            |
| `productId`        | `number`                    | Shopify-Produkt-ID.                                                                                                                                                                                                            |
| `variantId`        | `number`                    | Shopify-Varianten-ID.                                                                                                                                                                                                          |
| `line`             | `AftersellCartLine`         | Die vollständige [Cart-Zeile](/de/aftersell/cart/sdk-cart-object#cart-lines), für alles, was die obigen Props nicht abdecken.                                                                                                  |
| `formatMoney`      | `(cents: number) => string` | Formatiert einen Betrag in kleinster Einheit. Verwende sie für Preise, die du aus `line` liest.                                                                                                                                |

<Warning>
  **`price` und `compareAtPrice` sind formatierte Strings; alles auf `line` ist in Cent.** Rechne nicht mit `price`. Berechne mit `line.finalLinePrice` und Co. und schicke das Ergebnis dann durch `formatMoney`.
</Warning>

<div id="quantity-and-removal">
  ### Menge und Entfernen
</div>

| Prop                | Typ                                              | Wofür sie dient                                                                                                                                                                                                                                                           |
| ------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `increment`         | `() => void`                                     | Fügt der Zeile eins hinzu.                                                                                                                                                                                                                                                |
| `decrement`         | `() => void`                                     | Entfernt eins von der Zeile.                                                                                                                                                                                                                                              |
| `remove`            | `() => void`                                     | Entfernt die Zeile vollständig.                                                                                                                                                                                                                                           |
| `quantityInput`     | `string`                                         | Aktueller Wert für ein kontrolliertes Mengen-`<input>`. Ein String, damit Zwischenzustände beim Tippen erhalten bleiben.                                                                                                                                                  |
| `onQuantityInput`   | `(event: Event) => void`                         | `onInput`-Handler für dieses Feld.                                                                                                                                                                                                                                        |
| `commitQuantity`    | `() => void`                                     | Übernimmt die eingegebene Menge. An `onBlur` binden.                                                                                                                                                                                                                      |
| `onQuantityKeyDown` | `(event: KeyboardEvent) => void`                 | `onKeyDown`-Handler, damit Enter bestätigt.                                                                                                                                                                                                                               |
| `busy`              | `boolean`                                        | `true`, während eine Cart-Mutation läuft. Deaktiviere darauf deine Steuerelemente.                                                                                                                                                                                        |
| `pending`           | `'increment' \| 'decrement' \| 'remove' \| null` | Welche Aktion gerade läuft, für einen gezielten Spinner.                                                                                                                                                                                                                  |
| `stepperLocked`     | `boolean`                                        | `true`, wenn die Menge nicht geändert werden kann, weil die Zeile ein Bundle-Anker mit einem Kind mit gebrochener Rate pro Anker ist. Blende den Mengenwähler aus oder deaktiviere ihn — die integrierten Handler lehnen Änderungen bereits ab, solange dies gesetzt ist. |

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  return (
    <div className="cart-external-cart-items__row" style={{ display: 'flex', gap: '12px', opacity: props.busy ? 0.6 : 1 }}>
      {props.imageUrl && <img src={props.imageUrl} alt="" width={64} height={64} />}

      <div style={{ flex: 1 }}>
        {props.url ? <a href={props.url}>{props.title}</a> : <span>{props.title}</span>}
        {props.variantTitle && <div style={{ opacity: 0.6 }}>{props.variantTitle}</div>}
        {props.sellingPlanLabel && <div style={{ opacity: 0.6 }}>{props.sellingPlanLabel}</div>}

        {props.discountTags.map((tag) => (
          <span key={tag} style={{ fontSize: '11px', border: '1px solid', borderRadius: '4px', padding: '1px 5px' }}>
            {tag}
          </span>
        ))}

        {!props.stepperLocked && (
          <div style={{ display: 'flex', alignItems: 'center', gap: '6px', marginTop: '6px' }}>
            <button type="button" onClick={props.decrement} disabled={props.busy}>&minus;</button>
            <input
              value={props.quantityInput}
              onInput={props.onQuantityInput}
              onBlur={props.commitQuantity}
              onKeyDown={props.onQuantityKeyDown}
              size={2}
            />
            <button type="button" onClick={props.increment} disabled={props.busy}>+</button>
            <button type="button" onClick={props.remove} disabled={props.busy}>
              {props.pending === 'remove' ? 'Removing…' : 'Remove'}
            </button>
          </div>
        )}
      </div>

      <div style={{ textAlign: 'right' }}>
        <div>{props.price}</div>
        {props.compareAtPrice && <s style={{ opacity: 0.5 }}>{props.compareAtPrice}</s>}
        {props.savingsHtml && <div dangerouslySetInnerHTML={{ __html: props.savingsHtml }} />}
      </div>
    </div>
  );
}
```

<div id="rendering-a-bundle">
  ### Ein Bundle rendern
</div>

Auf der Ankerzeile eines Bundles enthält `bundle.children` dessen Inhalte. Kinder erscheinen nie als eigene Zeilen — wenn du sie nicht renderst, sieht der Kunde also nicht, was im Bundle ist:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  return (
    <div>
      <div>{props.title} {props.price}</div>

      {props.bundle && (
        <ul style={{ margin: '4px 0 0 12px', fontSize: '12px', opacity: 0.7 }}>
          {props.bundle.children.map((child, i) => (
            <li key={child.key ?? i}>{child.quantity} × {child.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}
```

Der `key` eines Kindes ist bei einer nativen Shopify-Bundle-Komponente `null`, greife also wie oben auf den Index zurück.

<div id="design">
  ## Design
</div>

Gestalte diesen Block über seinen Abschnitt **Design** im Einstellungspanel. Dies sind Überschreibungen pro Block, die auf deinem globalen Design aufsetzen und darauf zurückfallen, wenn sie leer sind.

Was sind Design-Einstellungen? Mehr erfährst du hier: [Design-Einstellungen](/de/aftersell/cart/design-settings).
