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

# Ocultar y reetiquetar líneas del carrito

> Un caso de uso del Cart SDK que usa transformaciones de línea y comparadores para ocultar líneas inyectadas por apps, renombrarlas y controlar el orden en que se renderizan.

Oculta líneas que el comprador no debería ver, renombra líneas que se leen mal y controla el orden en que todo se renderiza, todo sin tocar lo que realmente está en el carrito.

Esto reemplaza el patrón antiguo de ocultar elementos del carrito con CSS o `style.display = 'none'`. Una transformación de línea se aplica cada vez que el carrito se renderiza, así que sobrevive a actualizaciones, re-renderizados y reaperturas del drawer.

<div id="hide-a-line">
  ## Ocultar una línea
</div>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Hide free lines from the drawer. The cart total is unchanged.
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.finalLinePrice === 0) {
    line.setHidden(true);
  }
});
```

<Warning>
  **Ocultar no es eliminar.** Una línea oculta permanece en el carrito del comprador, permanece en el total y llega al checkout; simplemente no se dibuja en el drawer. Sí desaparece de `getCart().items` y de `itemCount`, así que tu propio código también deja de verla. Si quieres que desaparezca de verdad, usa [`removeItem`](/es/aftersell/cart/sdk-actions#removeitemkey).
</Warning>

Cosas comunes que vale la pena ocultar:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  // An app-injected line, tagged with a private property.
  if (line.properties?._bundle_child) {
    line.setHidden(true);
  }

  // A specific SKU that shouldn't be shopper-managed.
  if (line.variantId === HIDDEN_VARIANT_ID) {
    line.setHidden(true);
  }

  // Gift cards issued by a loyalty app.
  if (line.isGiftCard && line.finalLinePrice === 0) {
    line.setHidden(true);
  }
});
```

<div id="relabel-a-line">
  ## Reetiquetar una línea
</div>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  // Flag discounted lines.
  if (line.finalLinePrice < line.originalLinePrice) {
    line.setTitle(`${line.title} (On sale)`);
  }

  // Make the subscription cadence read naturally.
  if (line.sellingPlan) {
    line.setVariantTitle(`Delivered ${line.sellingPlan.name.toLowerCase()}`);
  }

  // Drop a meaningless variant label.
  if (line.variantTitle === 'Default Title') {
    line.setVariantTitle(null);
  }
});
```

Los cuatro setters disponibles en una línea:

| Setter                            | Efecto                                                                                                                                                   |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setHidden(bool)`                 | Oculta la línea del drawer.                                                                                                                              |
| `setTitle(string)`                | Cambia el título mostrado.                                                                                                                               |
| `setVariantTitle(string \| null)` | Cambia la etiqueta de variante mostrada. `null` la elimina.                                                                                              |
| `setInternalProperties(obj)`      | Fusiona propiedades de solo renderizado, para que un [bloque Custom code](/es/aftersell/cart/custom-code-blocks) las lea. Nunca se persisten en Shopify. |

<div id="control-the-order">
  ## Controlar el orden
</div>

Un comparador toma la misma forma que espera `Array.prototype.sort`, y se ejecuta después de ocultar y renombrar:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Subscriptions first, then everything else.
window.aftersell.cart.hooks.registerLineComparator((lineA, lineB) => {
  return (lineB.sellingPlan ? 1 : 0) - (lineA.sellingPlan ? 1 : 0);
});
```

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Push free gifts and add-ons to the bottom.
window.aftersell.cart.hooks.registerLineComparator((lineA, lineB) => {
  return (lineA.finalLinePrice === 0 ? 1 : 0) - (lineB.finalLinePrice === 0 ? 1 : 0);
});
```

Devuelve `0` para los pares que no te importan. Los comparadores se componen como criterios de desempate, así que el primero en devolver un valor distinto de cero decide ese par, y devolver `0` le pasa la decisión al siguiente en lugar de imponerle un orden.

<div id="hide-a-whole-block-not-a-line">
  ## Ocultar un bloque completo, no una línea
</div>

Una transformación de línea funciona sobre las líneas del carrito. Para mostrar configuraciones de **bloque** diferentes por país, mercado o moneda (por ejemplo, distintos niveles de Rewards), usa las [condiciones en el editor del carrito](/es/aftersell/cart/blocks-overview#show-or-hide-by-market-country-or-currency). No se requiere código, y sobrevive a rediseños del carrito. El total del carrito y el contenido del carrito **no** son tipos de condición del editor.

Recurre al SDK cuando tu regla sea algo que las condiciones no pueden expresar (IDs de producto en el carrito, un total personalizado, etcétera). En ese caso, consulta el [shadow root](/es/aftersell/cart/sdk-overview#shadowroot) buscando una clase pública `cart-external-*`:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (state) => {
  const root = window.aftersell.cart.shadowRoot;
  if (!root) return;

  const rewards = root.querySelector('.cart-external-rewards');
  if (!rewards) return;

  const hasExcluded = state.items.some((line) => EXCLUDED_PRODUCT_IDS.includes(line.productId));
  rewards.style.display = hasExcluded ? 'none' : '';
});
```

<Warning>
  Esto se ejecuta después de cada renderizado, así que el bloque puede aparecer fugazmente antes de que tu código lo oculte. El renderizado condicional no tiene ese problema, así que prefiérelo donde encaje.
</Warning>

<div id="things-to-get-right">
  ## Cosas que hay que hacer bien
</div>

* **Las transformaciones son llamadas de configuración.** Regístralas al principio de tu script de Initialization; no se necesita `ready()`.
* **Las transformaciones de todos se ejecutan.** La tuya se compone con cualquiera registrada por otras apps. No puedes reemplazar las suyas, y ellas no pueden descartar la tuya.
* **Una transformación no puede cambiar el precio, la cantidad ni la identidad.** Solo cambia lo que se renderiza. Usa las [acciones](/es/aftersell/cart/sdk-actions) para cambios reales.
* **Una transformación que lanza una excepción se omite silenciosamente.** El resto sigue ejecutándose. Revisa [`aftersellCartDebugEvents`](/es/aftersell/cart/sdk-overview#debugging) mientras desarrollas.
* **`registerLineTransform` devuelve una función de anulación de registro**, si necesitas deshacerlo más tarde.

<div id="where-to-go-next">
  ## Adónde ir después
</div>

* **[Hooks](/es/aftersell/cart/sdk-hooks)**: la referencia completa de hooks.
* **[Objeto cart](/es/aftersell/cart/sdk-cart-object)**: cada campo sobre el que puedes ramificar.
* **[Custom CSS](/es/aftersell/cart/custom-css)**: la convención de clases `cart-external-*`.
