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$eventwill 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-datahandler, this makes sense sincex-datais 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,$watchare accessible onthis.$eventand$dispatchare 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
thisfor function components/handlers (this.$el,this.$refs,this.$nextTick,this.$watch) - how to pass magic properties which are not available on
thisto function handlers from the template ($eventand$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?
Power up your debugging with the Alpine.js Devtools Extension for Chrome and Firefox. Trusted by over 15,000 developers (rated 4.5 ⭐️).