Andrei RRR
Andrei RRR

Reputation: 3162

Run function on load with AlpineJS

I have a button that on click it displays a toast message. I am trying to display the toast message automatically when the button is displayed (without having to click on it).

This is my code:

<button x-data
    @click="$dispatch('notice', {type: 'success', text: '🔥 Success!'})"
    class="m-4 bg-green-500 text-lg font-bold p-6 py-2 text-white shadow-md rounded">
    Success
</button>

<div
    x-data="noticesHandler()"
    class="fixed inset-0 flex flex-col-reverse items-end justify-start h-screen w-screen"
    @notice.window="add($event.detail)"
    style="pointer-events:none">
    <template x-for="notice of notices" :key="notice.id">
        <div
            x-show="visible.includes(notice)"
            x-transition:enter="transition ease-in duration-200"
            x-transition:enter-start="transform opacity-0 translate-y-2"
            x-transition:enter-end="transform opacity-100"
            x-transition:leave="transition ease-out duration-500"
            x-transition:leave-start="transform translate-x-0 opacity-100"
            x-transition:leave-end="transform translate-x-full opacity-0"
            @click="remove(notice.id)"
            class="rounded mb-4 mr-6 w-56  h-16 flex items-center justify-center text-white shadow-lg font-bold text-lg cursor-pointer"
            :class="{
                'bg-green-500': notice.type === 'success',
                'bg-blue-500': notice.type === 'info',
                'bg-orange-500': notice.type === 'warning',
                'bg-red-500': notice.type === 'error',
            }"
            style="pointer-events:all"
            x-text="notice.text">
        </div>
    </template>
</div>

<script>
    function noticesHandler() {
        return {
            notices: [],
            visible: [],
            add(notice) {
                notice.id = Date.now()
                this.notices.push(notice)
                this.fire(notice.id)
            },
            fire(id) {
                this.visible.push(this.notices.find(notice => notice.id == id))
                const timeShown = 2000 * this.visible.length
                setTimeout(() => {
                    this.remove(id)
                }, timeShown)
            },
            remove(id) {
                const notice = this.visible.find(notice => notice.id == id)
                const index = this.visible.indexOf(notice)
                this.visible.splice(index, 1)
            },
        }
    }
</script>

Tried to do it with x-init but it doesn't work:

<button x-data
        x-init="$dispatch('notice', {type: 'success', text: '🔥 Success!'})"
        class="m-4 bg-green-500 text-lg font-bold p-6 py-2 text-white shadow-md rounded">
        Success
    </button>

Any ideas on how I can do this?

Upvotes: 3

Views: 18230

Answers (1)

Dauros
Dauros

Reputation: 10502

You need to also use the $nextTick magic here, because x-init fires before the noticesHandler() component is ready.

<button x-data
    x-init="$nextTick(() => {$dispatch('notice', {type: 'success', text: '🔥 Success!'})})"
    class="m-4 bg-green-500 text-lg font-bold p-6 py-2 text-white shadow-md rounded">
    Success
</button>

This way x-init waits until Alpine.js finishes DOM updates, so basically each component is ready.

Upvotes: 9

Related Questions