Description: Custom directives allow you to create
new x- attributes using Alpine.directive().
This powerful feature enables you to encapsulate reusable DOM
manipulation logic or integrate with third-party JavaScript libraries,
effectively extending Alpine's built-in vocabulary. This is
particularly useful for behaviors that need to interact directly with
DOM elements in a structured and reusable way.
Alpine.directive('name', (el, { expression, modifiers }, {
evaluate, effect, cleanup }) => { ... }): This is the core function for registering a new custom
directive.
'name': A string representing the name of your
directive. If you name it 'foo', you'll use it in
HTML as x-foo.
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 value
passed to the directive attribute (e.g., in
x-foo="bar()", expression is
"bar()").
modifiers: An array of strings representing
any modifiers appended to the directive name (e.g., in
x-foo.once.debounce.500ms,
modifiers would be
['once', 'debounce', '500ms']).
{ evaluate, effect, cleanup }: An object
containing utility functions provided by Alpine:
evaluate(expressionString): Executes a
JavaScript expression string within the reactive scope of
the Alpine component the directive belongs to. This is
useful for getting data or functions from the component.
effect(() => { ... }): Registers a
callback function that Alpine will execute. Crucially,
Alpine tracks any reactive properties accessed within this
callback. If any of those properties change, Alpine will
re-run the callback. This makes your directive reactive.
cleanup(() => { ... }): Registers a
callback function that Alpine will execute when the
element is removed from the DOM or when the component it
belongs to is destroyed. This is essential for cleaning up
resources like event listeners, observers, or timers to
prevent memory leaks.
alpine:init: This is a JavaScript event dispatched
on the document object when Alpine.js has fully
initialized and is ready to start processing components and
directives. It's crucial to register your custom directives (and
global stores or data components) *inside* an event listener for
alpine:init. This ensures that Alpine knows about
your custom directive *before* it scans the DOM for attributes.
document.addEventListener('alpine:init', () => {
Alpine.directive('my-directive', (el) => {
// Directive logic here
});
});
x-data, x-text, and your custom ones)
during its initialization phase. If you define a custom directive
*after* Alpine has already processed an element that uses it, the
directive won't be applied to that element. Always register
directives within a
document.addEventListener('alpine:init', () => { ...
})
callback.
effect for reactivity: If your
directive needs to react to changes in Alpine component data,
you must wrap the relevant logic in an
effect callback. Simply accessing component data
once won't make the directive update automatically.
cleanup: If your directive sets up
event listeners, MutationObservers, ResizeObservers,
intervals, or timeouts, you *must* use the
cleanup callback to remove them. Failing to do so
can lead to memory leaks and unexpected behavior, especially
in single-page applications or when components are dynamically
added and removed.
expression vs evaluate(expression):
The expression parameter is just a string. To
execute it as JavaScript in the context of the Alpine
component, you need to pass it to the
evaluate() utility. For example, if
x-my-directive="myFunction(someData)",
expression is the string
"myFunction(someData)".
evaluate(expression) would actually call
myFunction with someData from the
component's scope.
el: The el parameter refers
to the specific DOM element the directive is attached to.
Operations on el are direct DOM manipulations.
This example demonstrates a custom directive
x-resize-observer. This directive uses the browser's
ResizeObserver API
to monitor an element for size changes and calls a specified component
method with the new dimensions.
Width:
0
px
Height:
0
px
The x-resize-observer="updateDimensions" directive on
the textarea instructs Alpine to call the
updateDimensions method of our component whenever the
textarea's size changes. The custom directive encapsulates the
logic for setting up and cleaning up the
ResizeObserver.