Advanced x-data Patterns

Reusable, parameterized, and composable components.

Reusable & Composable Components

As your Alpine app grows, you'll want to avoid repeating component logic. Alpine.data() and Alpine.bind() let you define components that can be reused, parameterized, and even composed together using mixins.

Parameterized Components

Data factories can accept arguments, allowing you to customise each instance.

Code
Alpine.data('modal', (initialOpen = false, size = 'medium') => ({
  open: initialOpen,
  size: size,
  init() {
    console.log('Modal initialized with size:', size)
  },
  close() { this.open = false }
}))
// Usage: <div x-data="modal(true, 'large')">

Nested Components & Communication

Nested x-data components have independent scopes. They can communicate using $dispatch (for child→parent) and $store (for any shared state).

Alpine.merge() for Mixins

You can mix multiple data factories into one using Alpine.merge(). This is similar to mixins in Vue.

Code
Alpine.data('togglable', () => ({ open: false, toggle() { this.open = !this.open } }))
Alpine.data('closable', () => ({ close() { this.open = false } }))

Alpine.data('dialog', () => ({
  ...Alpine.merge(Alpine.data('togglable'), Alpine.data('closable'))
}))

Extracting Business Logic

For complex logic, keep your Alpine.data() factories clean by extracting pure functions or services. This makes unit testing trivial.

Code
// utils.js
export function formatPrice(amount) {
  return '$' + amount.toFixed(2)
}

// alpine-component.js
Alpine.data('product', () => ({
  price: 9.99,
  get formattedPrice() { return formatPrice(this.price) }
}))

💡 Tip

Use TypeScript with Alpine? Export your data factories as typed functions for better auto‑completion and safety.

Helpful? Share this page!↑ Back to top