Description: Create new x- attributes using Alpine.directive() to encapsulate reusable DOM manipulation logic or integrate with third-party libraries, extending Alpine's vocabulary. This allows you to define custom behaviors tied directly to HTML elements, much like Alpine's built-in directives (e.g., x-show, x-if).
The core of creating custom directives is the Alpine.directive() method:
Alpine.directive('name', (el, { expression, modifiers }, { evaluate, effect, cleanup }) => {
// Directive logic here
});
'name': The name of your custom directive. This will be used in HTML as x-name. For example, if you name it 'tooltip', you'd use x-tooltip.el: The DOM element the directive is attached to. You can directly manipulate this element.{ expression, modifiers }: An object containing:
expression: A string representing the JavaScript expression passed to the directive. For x-tooltip="'Hello World'", the expression is "'Hello World'".modifiers: An array of strings representing any modifiers applied to the directive. For x-foo.bar.baz, modifiers would be ['bar', 'baz'].{ evaluate, effect, cleanup }: An object containing utility functions:
evaluate(expression): Evaluates a JavaScript expression within the current Alpine reactive scope. This is useful for getting the value of the directive's expression.effect(() => { ... }): Executes a callback function and re-runs it whenever any of its reactive dependencies change. This is crucial for directives that need to update based on changing data.cleanup(() => { ... }): Registers a callback function to be executed when the element is removed from the DOM or the directive is cleaned up. Use this for removing event listeners, timers, or any other resources.alpine:init Event:
Custom directives must be registered before Alpine.js initializes and scans the DOM. The standard way to do this is by listening for the alpine:init event on the document:
document.addEventListener('alpine:init', () => {
Alpine.directive('my-directive', (el, ...) => { /* ... */ });
// Other Alpine.data, Alpine.store registrations can also go here
});
alpine:init event listener. If you try to register a directive after Alpine has already initialized, it won't recognize your new x-attribute on elements that were processed during the initial scan. This is like trying to use a Python function before it's defined; the interpreter (or in this case, Alpine) won't know what to do.
el, expression, modifiers, and the utility functions evaluate, effect, cleanup) are your tools.
evaluate(expression) when you need the *value* of the expression is a common mistake. The expression itself is just a string.effect when your directive's behavior depends on reactive data will lead to it not updating when that data changes.cleanup can lead to memory leaks, especially if you're adding event listeners or creating DOM elements dynamically within the directive. Imagine forgetting to close a file handle in Python – similar principle.evaluate and effect operate within Alpine's reactive system. This is powerful but requires understanding how Alpine tracks dependencies.
el, be mindful of how your manipulations interact with Alpine's own DOM updates, especially if the element is also managed by x-if or x-for.
Hover over the items below to see a custom tooltip in action. The tooltip's content and behavior are defined by our x-custom-tooltip directive.