/ Gists / Alpine.js

Gists - Alpine.js

On gists

Sandbox skeleton (demo code) tailwind, alpine

Popular ⭐ Tailwind CSS Alpine.js

index.html #

<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <title>Sandbox - RJ</title>
    <meta name="description" content="" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://unpkg.com/@tailwindcss/browser@4"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
  </head>
  <body>
  
   <!-- Code here ... -->
   
   
    
  </body>
</html>

On gists

Alpine reactivity like jQuery

Alpine.js

reactivity.js #

let button = document.querySelector('button')
let span = document.querySelector('span')
 
let proxy = Alpine.reactive({ color: ‘blue’ })
 
Alpine.effect(() => {
    span.textContent = proxy.color
})
 
button.addEventListener('click', () => {
    proxy.color = (proxy.color == ‘blue’) ? ‘green’ : ‘blue’
}) 

On gists

Fetch / async

Alpine.js

fetch-async-ways.js #

async function getItems() {
    let response = await fetch('/api/items/all')
    let json = await response.json()
    return json
}

<div x-text="JSON.stringify(getItems())"></div>

// or alternatively:
<div
    x-data="{
        items: {},

        async getItems() {
            this.items = await (await fetch('/api/items/all')).json();
        }
    }"
    x-init="getItems">
</div>

On gists

Alpine - magic (custom method)

Alpine.js

overlap.js #

// https://github.com/markmead/alpinejs-overlap/blob/main/src/index.js

export default function (Alpine) {
  Alpine.magic('overlap', (el, {}) => (targetId) => {
    const targetEl = document.querySelector(targetId)

    return checkOverlap(
      targetEl.getBoundingClientRect(),
      el.getBoundingClientRect()
    )
  })

  function checkOverlap(targetBounding, elBounding) {
    return !(
      targetBounding.top > elBounding.bottom ||
      targetBounding.right < elBounding.left ||
      targetBounding.bottom < elBounding.top ||
      targetBounding.left > elBounding.right
    )
  }
}

On gists

Alpine directive - slugify

Alpine.js

slugify.js #

// https://github.com/markmead/alpinejs-slug

import slugify from 'slugify'

export default function (Alpine) {
  Alpine.directive('slug', (el, { expression }, { evaluateLater, effect }) => {
    let setInputValue = evaluateLater(expression)

    effect(() => {
      setInputValue((string) => {
        el.value = slugify(string, {
          lower: true,
        })
      })
    })
  })
}

On gists

Alpine js - directive (example)

Alpine.js

example.js #

//  https://github.com/markmead/alpinejs-textarea-autogrow

export default function (Alpine) {
  Alpine.directive('grow', (el) => {
    el.addEventListener('input', () => {
      el.style.height = 'auto'

      el.style.height = `${el.scrollHeight}px`
    })
  })
}

On gists

TodoList

Alpine.js

index.html #

<!-- https://codepen.io/ryangjchandler/pen/qBOEgjg -->

<div x-data="toDoList()" class="max-w-2xl mx-auto px-12 py-8 rounded-lg shadow-lg bg-gray-200">
    <div class="flex flex-col items-center justify-center mb-8">
        <h1 class="text-3xl font-bold mb-8">
            To Do List
        </h1>
        <input type="text" x-model="newTodo" placeholder="I need to..." class="mx-auto px-4 py-2 rounded shadow text-lg min-w-full" @keydown.enter="addToDo">
    </div>
    <div class="bg-white w-full rounded shadow mb-8">
        <template x-for="(todo, index) in todos" :key="index">
            <div class="flex items-center py-4" :class="{ 'border-b border-gray-400': ! isLastToDo(index) }">
                <div class="w-1/12 text-center">
                    <input type="checkbox" @change="toggleToDoCompleted(index)" :checked="todo.completed">
                </div>
                <div class="w-10/12">
                    <p x-text="todo.todo" :class="{ 'line-through': todo.completed }"></p>
                </div>
                <div class="w-1/12 text-center">
                    <button class="bg-red-600 text-white px-2 py-1 rounded hover:bg-red-700" @click="deleteToDo(index)">
                        &cross;
                    </button>
                </div>
            </div>
        </template>
    </div>
    <div>
        <span x-text="numberOfToDosCompleted()"></span> / <span x-text="toDoCount()"></span> to dos completed
    </div>
</div>


<script>
  function toDoList() {
    return {
        newTodo: "",
        todos: [],
        addToDo() {
            this.todos.push({
                todo: this.newTodo,
                completed: false
            });

            this.newTodo = "";
        },
        toggleToDoCompleted(index) {
            this.todos[index].completed = !this.todos[index].completed;
        },
        deleteToDo(index) {
            this.todos = this.todos.filter((todo, todoIndex) => {
                return index !== todoIndex
            })
        },
        numberOfToDosCompleted() {
            return this.todos.filter(todo => todo.completed).length;
        },
        toDoCount() {
            return this.todos.length
        },
        isLastToDo(index) {
            return this.todos.length - 1 === index
        }
    };
}

  
</script>

On gists

Alpine.js tricks

Alpine.js

tricks.html #

<!-- 1. Automatic init function calls -->
<div x-data="{
    init() {
        console.log('Here we go!')
    }
}"></div>

<!-- 2. Clean up after yourself with destroy -->
<div x-data="{
    init() {
        carouselLibrary.create();
    },
    destroy() {
        carouselLibrary.delete();
    }
}"></div>

<!-- 3. Interact with global stores from external JavaScript -->
Alpine.store('counter', {
    count: 0
})
// In a different file or area.
Alpine.store('counter').count += 1

<!-- 4. Independent x-init directives -->
<div x-data>
    <p x-init="console.log('I am ready!')"></p>
</div>

<img src="..." x-init="doSomeMagicHere()">


<!-- 5. Unfurl / unwrap Proxy with Alpine.raw -->
<div x-data="{ user: { name: 'Ryan' } }" x-init="console.log(user)">
    <!-- This produces a `Proxy` in the console -->
</div>

<div x-data="{ user: { name: 'Ryan' } }" x-init="console.log(Alpine.raw(user))">
    <!-- This produces the "real" `user` object in the console -->
</div>

On gists

Custom event (flash event ;).

Alpine.js

index.html #

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Alpine Examples</title>

    <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js"
            defer
    ></script>

    <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
          rel="stylesheet"
    >
</head>

<body class="p-12">
    <!-- Flash -->
    <div
        x-data="{ show: false, message: '' }"
        x-show.transition.opacity.scale.75.duration="show"
        @flash.window="
            show = true;
            message = $event.detail;
            setTimeout(() => show = false, 3000);
        "
        x-text="message"
        class="fixed bottom-0 right-0 mb-4 mr-4 bg-blue-500 text-white p-4 rounded"
    >

    </div>

    <script>
        // Additionally, any component can call $dispatch('flash', 'A flash message');

        window.flash = message => window.dispatchEvent(new CustomEvent('flash', {detail: message}));
    </script>
</body>

</html>

On gists

Remove via $event / $el

Alpine.js

remove.html #

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="//unpkg.com/alpinejs" defer></script>
</head>
<body>
  <div x-data>
      <button @click="$el.remove()">remove me 1</button>
      <button @click="$event.target.remove()">remove me 2</button>
  </div>
</body>
</html>