How to Access Alpine.js Magic Properties from inline handlers and function/component methods
Alpine.js magic properties are crucial to leveraging its best features.
When using Alpine.js in a “mainly markup” configuration (no script tags), the magic properties tend to be accessible seamlessly.
Alpine.js magic properties are as follows:
$el
: the element to which an Alpine.js component is bound (also called the root element)$refs
: references to DOM Nodes as defined in the markup for an Alpine.js component$event
: (only exists in templates) when adding an event handler, using$event
will pass the full event into the handler.$dispatch
: dispatch a custom event see A guide to Alpine.js component communication$nextTick
: delay running of a function (callback) until after Alpine.js has updated/rendered$watch
: run a function (callback) on every change to a reactive property.
Table of Contents
Access to magic properties in Alpine.js templates
There’s no official Alpine.js “template” definition but I’ll call all the elements inside of the root element (the one that has the x-data
attribute), the “template”.
In your Alpine.js template, you can access the magic properties directly.
For example:
<div x-data="{}" x-init="console.log($el)">
<button @click="$dispatch('toggle')">Toggle</button>
</div>
The x-init
inline handler uses the $el
magic property (& logs it out).
The @click
inline handler uses the $dispatch
magic property to dispatch a toggle
custom event when the “Toggle” button is clicked.
This example is lifted from A guide to Alpine.js component communication, head over there for more in-depth use-cases for $dispatch
.
We’ve now seen how to access magic properties in inline-handlers.
Next we’ll look at the state of magic property access on this
in Alpine.js “function components”.
Magic properties on this
in JavaScript function components in Alpine.js
Alpine.js “function components” are components that define x-data
as a function call eg. x-data="someFunction()"
. Which allows you to define your component logic in a script tag (as long as it exposes a function on window
).
This is in contrast using the inline x-data
object definition eg. x-data="{ isOpen: false }"
and inline handlers such as @click="isOpen = !isOpen
.
Given the following component with inline handlers:
<div x-data="{ isOpen: false }">
<p x-show="isOpen">
What you can toggle
</p>
<button @click="isOpen = !isOpen">
Toggle
</button>
</div>
We can write it as a function component as follows. Note how we’ve extracted the isOpen
toggling to a function and how the component
function returns initial state for x-data and the functions needed in the component (in this case toggle
).
<div x-data="component()">
<p x-show="isOpen">
What you can toggle
</p>
<button @click="toggle()">
Toggle
</button>
</div>
<script>
function component() {
return {
isOpen: false,
toggle() {
this.isOpen = !this.isOpen;
}
}
}
</script>
From the previous section we know that in inline handlers, we can access magic properties simply by referring to them.
It would be reasonable to expect that magic properties are available on this
just as they are in inline handlers. This is not the case.
See the following table for reference (up to date as of Alpine.js v2.3.x). A runnable version is available at Alpine.js Magic Properties on this
- Alpine.js Playground.
The table shows that:
- no magic properties are available for the
x-data
handler, this makes sense sincex-data
is run before the component context (this
) exists - for all other directive handlers (x-init, x-text, x-html, x-bind, x-show, x-on):
$el
,$refs
,$nextTick
,$watch
are accessible onthis
.$event
and$dispatch
are not available onthis
.
type | available magic properties on this | unavailable magic properties on this |
---|---|---|
x-data handler | none | $el, $refs, $event, $dispatch, $nextTick, $watch |
x-init handler | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-text handler | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-html handler | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-bind handler | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-show handler | $el, $refs, $nextTick, $watch | $event, $dispatch |
x-on handler | $el, $refs, $nextTick, $watch | $event, $dispatch |
You can for example in an x-init
handler use the $watch
magic property this.$watch('foo', (val) => console.log(val))
and so on for other types of directive handlers and magic properties that are available on this
(this.$el
, this.$refs
, this.$nextTick
, this.$watch
).
We’ve now seen what a function component is and which magic properties are available on this
.
Next we’ll see how to access $dispatch
in x-init
by passing it from the template.
Access $dispatch magic property in x-init by passing it from the template.
The following is an example of how one would access $dispatch
in the handler for x-init
in an Alpine.js function component.
We can pass $dispatch
into the function from the template, it can then be used without issue.
<div
x-data="page()"
x-init="init($dispatch)"
>
<p x-text="output"></p>
</div>
<script>
function page() {
return {
output: '',
init($dispatch) {
// this.$dispatch is **not** defined in x-init handler
this.output += "Calling $dispatch";
$dispatch('test');
this.output += "\nCalled $dispatch";
},
};
}
</script>
You can see the full example at Alpine.js Magic Property access in JavaScript - Alpine.js Playground.
We’ve now see how to pass $dispatch
into x-init
function handlers from the template.
Next we’ll see how to access $event
and $dispatch
in the case of Alpine.js x-on
function handlers.
Access $event and $dispatch in x-on handlers by passing it from the template
Note this approach of passing $dispatch from the template will work for handlers for other directives, x-on handlers are the most likely to need to use
$dispatch
.
The following example is an Alpine.js function component setup which contains a button with value="button-value"
, on click, we would like to be able to read the event.target.value
and dispatch a custom event.
In order to achieve this, we pass the $event
and $dispatch
magic properties into the handleClick
handler. This makes them available as parameters for handleClick
.
<div
x-data="page()"
>
<p x-text="output"></p>
<button
@click="handleClick($event, $dispatch)"
value="button-value"
>
Get $event and $dispatch on click
</button>
</div>
<script>
function page() {
return {
output: '',
handleClick(e, $dispatch) {
// this.$event and this.$dispatch are **not** defined in x-on handler
this.output += `\nevent.target.value: "${e.target.value}"`;
this.output += "\nCalling $dispatch";
$dispatch("test2");
this.output += "\nCalled $dispatch";
},
};
}
</script>
You can see the full example at Alpine.js Magic Property access in JavaScript - Alpine.js Playground.
We’ve now seen how to access $event
and $dispatch
magic properties in an x-on
function handler.
Through this post you should now have knowledge of:
- what magic properties are
- how to access them in the template
- which magic properties are available on
this
for function components/handlers (this.$el
,this.$refs
,this.$nextTick
,this.$watch
) - how to pass magic properties which are not available on
this
to function handlers from the template ($event
and$dispatch
)
That’s it for this post, you can check out the Alpine.js tag on Code with Hugo for more in-depth Alpine.js guides.
If you’re interested in Alpine.js, Subscribe to Alpine.js Weekly. A free, once–weekly email roundup of Alpine.js news and articles.
Photo by Aziz Acharki on Unsplash
Interested in Alpine.js?
Subscribe to Alpine.js Weekly. A free, once–weekly email roundup of Alpine.js news and articles