Table of Contents & Menu
On this page
Navigation

Alpine CSP x-data constructors

Alpine CSP restricts x-data usage: inline object initialization (e.g., x-data="{open: false}") and direct global function calls (e.g., x-data="initPriceBox") are not permitted due to security policies. Instead, x-data must refer to a function explicitly registered using Alpine.data().

<div x-data="initMyComponent">
    ...
</div>
<script>
    Alpine.data('initMyComponent', () => ({
        open: false
    }))
</script>

To ensure Alpine.data is available when your script runs, register your data function within an alpine:init event listener:

window.addEventListener(
    'alpine:init',
    () => Alpine.data('initMyComponent', () => ({
        open: false
    })),
    {once: true}
)

For better maintainability and extensibility (e.g., for proxying or wrapping as detailed in Overriding JavaScript), Hyvä typically uses named global functions. Here's how to register a named function with Alpine.data():

function initMyComponent() {
    return {
        open: false
    }
}

window.addEventListener(
    'alpine:init',
    () => Alpine.data('initMyComponent', initMyComponent),
    {once: true}
);

Merging objects

Hyvä often composes Alpine components by merging objects using Object.assign:

<form x-data="Object.assign(hyva.modal(), hyva.formValidation($el), {myValue: ''})">

As direct JavaScript expressions are disallowed in x-data within Alpine CSP, this object merging must be encapsulated within a constructor function:

function exampleCspComponent() {
  return Object.assign(
      hyva.modal.call(this),
      hyva.formValidation(this.$el),
      {
          myValue: ''
      }
  );
}

If any of the merged functions require the Alpine component's context (this), ensure you explicitly pass it using call() or apply(), as demonstrated with hyva.modal.call(this).