Skip to content

Instantly share code, notes, and snippets.

@blittle
Last active November 23, 2024 16:30
Show Gist options
  • Save blittle/19c3b88fc2a087d8c3dce75c251aec1c to your computer and use it in GitHub Desktop.
Save blittle/19c3b88fc2a087d8c3dce75c251aec1c to your computer and use it in GitHub Desktop.
Handling Repeated Content in Web Components

Handling Repeated Content in Web Components

The Challenge

When building a cart component, you often need to render multiple items with custom layouts. The intuitive approach might look like this:

<my-cart>
  <div slot="line-item">Custom line item layout</div>
</my-cart>

However, this doesn't work as expected because named slots can only be used once in a shadow DOM.

The Goal

We want to allow users to:

  1. Define a custom template for line items
  2. Access item-specific data within each line
  3. Maintain a clean, intuitive API

Possible Solutions

1. External Template (Suboptimal)

<!-- Feels disconnected -->
<template id="line-item">
  <my-line-item>
    <b><my-line-item-title></my-line-item-title></b>
  </my-line-item>
</template>
<my-cart line-item-template="line-item"></my-cart>

2. Internal Template (Better)

<my-cart>
  <!-- Regular slots work normally -->
  <div slot="header">Cart Header</div>
  
  <!-- Template for repeated items -->
  <template slot="line-item-template">
    <my-line-item>
      <b><my-line-item-title></my-line-item-title></b>
    </my-line-item>
  </template>
  
  <div slot="footer">Cart Footer</div>
</my-cart>

Alternative Approaches Worth Considering?

1. Render Props Pattern

<my-cart>
  <!-- Regular slots work normally -->
  <div slot="header">Cart Header</div>
  
  <script type="application/json" slot="line-item-renderer">
    (item) => `<my-line-item>${item.title}</my-line-item>`
  </script>
</my-cart>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment