Skip to content

Latest commit

 

History

History
179 lines (136 loc) · 4.63 KB

alpine-data.md

File metadata and controls

179 lines (136 loc) · 4.63 KB
order title
1
data()

Alpine.data

Alpine.data(...) provides a way to re-use x-data contexts within your application.

Here's a contrived dropdown component for example:

<div x-data="dropdown">
    <button @click="toggle">...</button>

    <div x-show="open">...</div>
</div>

<script>
    document.addEventListener('alpine:init', () => {
        Alpine.data('dropdown', () => ({
            open: false,

            toggle() {
                this.open = ! this.open
            }
        }))
    })
</script>

As you can see we've extracted the properties and methods we would usually define directly inside x-data into a separate Alpine component object.

Registering from a bundle

If you've chosen to use a build step for your Alpine code, you should register your components in the following way:

import Alpine from `alpinejs`
import dropdown from './dropdown.js'

Alpine.data('dropdown', dropdown)

Alpine.start()

This assumes you have a file called dropdown.js with the following contents:

export default () => ({
    open: false,

    toggle() {
        this.open = ! this.open
    }
})

Initial parameters

In addition to referencing Alpine.data providers by their name plainly (like x-data="dropdown"), you can also reference them as functions (x-data="dropdown()"). By calling them as functions directly, you can pass in additional parameters to be used when creating the initial data object like so:

<div x-data="dropdown(true)">
Alpine.data('dropdown', (initialOpenState = false) => ({
    open: initialOpenState
}))

Now, you can re-use the dropdown object, but provide it with different parameters as you need to.

Init functions

If your component contains an init() method, Alpine will automatically execute it before it renders the component. For example:

Alpine.data('dropdown', () => ({
    init() {
        // This code will be executed before Alpine
        // initializes the rest of the component.
    }
}))

Destroy functions

Like init(), Alpine will automatically discover and execute your component's destroy() method just prior to cleaning up other reactive properties.

Alpine.data('timer', (delay = 5000) => ({
    countdown: null,
    init () {
        this.countdown = window.setTimeout(() => {
            console.log('Time’s up!')
        }, delay)
    },
    destroy() {
        window.clearTimeout(this.countdown)
    },
}))
## Non-reactive Data

If you need to maintain a reference to something that is a dependency of your component (but not necessarily tracked by or compatible with Alpine’s reactivity engine), you can declare a variable within the factory function’s scope:

Alpine.data('super-dropdown', () => {
    let superSelectInstance

    return {
        init () {
            superSelectInstance = new SuperSelect(this.$el)
        },
        destroy() {
            // Supposing the library has its own global
            // event listeners that need cleanup:
            superSelectInstance.teardown()
        }
    }
})

Note the difference in the first line of this component definition—we're opening a function body, rather than using the arrow function’s implicit return feature, as in previous examples. Your component's final definition still takes the same shape, but must be explicitly returned by the factory function.

Using magic properties

If you want to access magic methods or properties from a component object, you can do so using the this context:

Alpine.data('dropdown', () => ({
    open: false,

    init() {
        this.$watch('open', () => {...})
    }
}))

Encapsulating directives with x-bind

If you wish to re-use more than just the data object of a component, you can encapsulate entire Alpine template directives using x-bind.

The following is an example of extracting the templating details of our previous dropdown component using x-bind:

<div x-data="dropdown">
    <button x-bind="trigger"></button>

    <div x-bind="dialogue"></div>
</div>
Alpine.data('dropdown', () => ({
    open: false,

    trigger: {
        ['@click']() {
            this.open = ! this.open
        },
    },

    dialogue: {
        ['x-show']() {
            return this.open
        },
    },
}))