Alpine.js at the Bowling Alley

Understanding $el, $refs, and $root

Action Log

1. $el: The Current Lane

$el refers to the DOM element the Alpine directive is attached to. It's like pointing at the specific lane you're on and saying "this one." In event handlers, it's the element that triggered the event.

Demonstration:

Click the button below. The action will use $el to modify the button itself.

Code Example

<!-- The button modifies itself using $el -->
<button @click="lightUpLane($el)">
    This is Lane 5
</button>

<script>
Alpine.data('elDemo', () => ({
  lightUpLane(element) {
    // 'element' is the DOM node passed via $el
    this.$store.statusLog.add('$el: Changing the element itself.');
    element.textContent = 'LANE 5 IS ACTIVE!';
    element.classList.add('bg-green-500', 'text-white');
    element.disabled = true;
  },
  reset() { ... }
}));
</script>

2. $refs: Named Equipment

$refs lets you access any element within your component that has an x-ref attribute. It's like having a control panel where you can press a button to operate a specific, named piece of equipment, no matter where it is.

Lane 6 Control Panel

Pinsetter: Pinsetter is idle
Ball Return: Ball return is empty
Monitor: SCORE: 0

Code Example

<!-- Name the equipment with x-ref -->
<div x-ref="pinsetter">...</div>
<div x-ref="ballReturn">...</div>

<!-- Control it from anywhere in the component -->
<button @click="activatePinsetter()">Activate</button>

<script>
Alpine.data('refsDemo', () => ({
  activatePinsetter() {
    this.$store.statusLog.add('$refs: Accessing pinsetter.');
    // Access the named element via this.$refs
    this.$refs.pinsetter.classList.add('bg-yellow-200');
    this.$refs.pinsetter.querySelector('span').textContent = '...';
  },
  reset() { ... }
}));
</script>

3. $root: The Entire Alley

$root refers to the root element of the component (the element with x-data). It's the "loudspeaker" for your component. An action can affect the entire area, changing the general state or appearance of all elements inside it.

Alley-Wide Controls

Lane 1
Lane 2
Lane 3
Lane 4

Code Example

<!-- The component root -->
<div x-data="rootDemo">
    <!-- Button to trigger the change -->
    <button @click="startCosmicBowling()">Go Cosmic</button>

    <!-- Other elements inside the component -->
    <div class="lane-box">...</div>
</div>

<script>
Alpine.data('rootDemo', () => ({
  startCosmicBowling() {
    this.$store.statusLog.add('$root: Changing the whole alley.');
    // 'this.$root' is the div with x-data
    this.$root.classList.add('bg-gray-900');
  },
  resetAlley() { ... }
}));
</script>