Frontend API Reference
Complete reference for all Alpine Gale magics, directives, and configuration APIs. Alpine Gale extends Alpine.js with server-driven capabilities through HTTP magics, directives, and reactive state management.
HTTP Magics
HTTP magics send requests to your server with automatic state serialization and SSE response handling.
Basic HTTP Methods
| Magic | Description |
|---|---|
$get(url, options?) |
Send GET request with state serialization |
$post(url, options?) |
Send POST request with state serialization |
$patch(url, options?) |
Send PATCH request with state serialization |
$put(url, options?) |
Send PUT request with state serialization |
$delete(url, options?) |
Send DELETE request with state serialization |
CSRF-Protected Methods
These magics automatically inject CSRF tokens and include credentials for session handling.
| Magic | Description |
|---|---|
$postx(url, options?) |
CSRF-protected POST request |
$patchx(url, options?) |
CSRF-protected PATCH request |
$putx(url, options?) |
CSRF-protected PUT request |
$deletex(url, options?) |
CSRF-protected DELETE request |
Request Options
All HTTP magics accept an optional second parameter for request options.
// Request options object
{
include: ['email', 'name'], // Only send these state keys
exclude: ['password'], // Don't send these state keys
headers: { // Additional HTTP headers
'X-Custom': 'value'
},
retryInterval: 1000, // Initial retry interval (ms)
retryScaler: 2, // Exponential backoff multiplier
retryMaxWaitMs: 30000, // Max retry interval (ms)
retryMaxCount: 10, // Max retry attempts
requestCancellation: 'auto' // 'auto' | 'disabled' | AbortController
}
// Request options object
{
include: ['email', 'name'], // Only send these state keys
exclude: ['password'], // Don't send these state keys
headers: { // Additional HTTP headers
'X-Custom': 'value'
},
retryInterval: 1000, // Initial retry interval (ms)
retryScaler: 2, // Exponential backoff multiplier
retryMaxWaitMs: 30000, // Max retry interval (ms)
retryMaxCount: 10, // Max retry attempts
requestCancellation: 'auto' // 'auto' | 'disabled' | AbortController
}
| Option | Type | Default | Description |
|---|---|---|---|
include |
array | null |
Whitelist of state keys to send |
exclude |
array | null |
Blacklist of state keys to exclude |
headers |
object | {} |
Additional HTTP headers |
retryInterval |
number | 1000 |
Initial retry delay in milliseconds |
retryScaler |
number | 2 |
Multiplier for exponential backoff |
retryMaxWaitMs |
number | 30000 |
Maximum retry interval |
retryMaxCount |
number | 10 |
Maximum number of retry attempts |
requestCancellation |
string|AbortController | 'auto' |
Request cancellation strategy |
Navigation Magic
$navigate
Programmatic SPA navigation with state serialization.
<!-- Basic navigation -->
<button @click="$navigate('/dashboard')">Go to Dashboard</button>
<!-- With options -->
<button @click="$navigate('/search', { merge: true })">
Search (keep query params)
</button>
<!-- Replace history -->
<button @click="$navigate('/login', { replace: true })">
Login
</button>
| Option | Type | Description |
|---|---|---|
merge |
boolean | Keep current query params, override with new |
only |
array | Keep only these query params |
except |
array | Keep all except these query params |
replace |
boolean | Replace history instead of push |
key |
string | Navigation key for backend filtering |
Component Magics
$components
Access and manage named components registered with x-component.
| Method | Description |
|---|---|
$components.get(name) |
Get component data by name |
$components.getByTag(tag) |
Get all components with a specific tag |
$components.all() |
Get all registered components |
$components.has(name) |
Check if component exists |
$components.invoke(name, method, ...args) |
Invoke a method on a component |
Timing Solutions
| Method | Description |
|---|---|
$components.when(name, timeout?) |
Promise that resolves when component ready |
$components.onReady(names, callback) |
Callback when component(s) become ready |
Reactive State CRUD
| Method | Description |
|---|---|
$components.state(name, key?) |
Get reactive state proxy for a component |
$components.update(name, updates) |
Update component state (RFC 7386 merge patch) |
$components.create(name, state, options?) |
Initialize state on a component |
$components.delete(name, keys) |
Delete properties from component state |
$components.watch(name, keyOrCb, cb?) |
Watch component state for changes |
<!-- Display cart total reactively -->
<span x-text="$components.state('cart')?.total"></span>
<!-- Update cart from another component -->
<button @click="$components.update('cart', { total: 99.99 })">
Set Total
</button>
<!-- Wait for component to be ready -->
<div x-init="$components.when('cart').then(c => console.log('ready', c))"></div>
<!-- Watch for state changes -->
<div x-init="$components.watch('cart', 'items', (items) => console.log(items))"></div>
$invoke
Shorthand for invoking methods on named components.
<!-- Invoke method on named component -->
<button @click="$invoke('cart', 'recalculate', 2.5)">
Recalculate Cart
</button>
<!-- Equivalent to -->
<button @click="$components.invoke('cart', 'recalculate', 2.5)">
Recalculate Cart
</button>
File Magics
Magics for handling file uploads with the x-files directive.
| Magic | Returns | Description |
|---|---|---|
$file(name) |
object|null | Get info for a single file input |
$files(name) |
array | Get array of file info for multiple files |
$filePreview(name, index?) |
string | Get preview URL for a file |
$clearFiles(name?) |
void | Clear file input(s) |
$formatBytes(size, decimals?) |
string | Format bytes to human-readable string |
$uploading |
boolean | Whether upload is in progress |
$uploadProgress |
number | Upload progress (0-100) |
$uploadError |
string|null | Upload error message |
<div x-data>
<input type="file" x-files="avatar">
<!-- Show file info -->
<template x-if="$file('avatar')">
<div>
<img :src="$filePreview('avatar')">
<p x-text="$file('avatar').name"></p>
<p x-text="$formatBytes($file('avatar').size)"></p>
<button @click="$clearFiles('avatar')">Remove</button>
</div>
</template>
<!-- Upload progress -->
<div x-show="$uploading">
<progress :value="$uploadProgress" max="100"></progress>
</div>
</div>
<div x-data>
<input type="file" x-files="avatar">
<!-- Show file info -->
<template x-if="$file('avatar')">
<div>
<img :src="$filePreview('avatar')">
<p x-text="$file('avatar').name"></p>
<p x-text="$formatBytes($file('avatar').size)"></p>
<button @click="$clearFiles('avatar')">Remove</button>
</div>
</template>
<!-- Upload progress -->
<div x-show="$uploading">
<progress :value="$uploadProgress" max="100"></progress>
</div>
</div>
State Magics
$gale
Global connection state tracking.
| Property | Type | Description |
|---|---|---|
$gale.loading |
boolean | Whether any request is in progress |
$gale.error |
string|null | Current error message |
$gale.retrying |
boolean | Whether a retry is in progress |
$fetching
Per-element loading state. Returns true when the current component is making a request.
<div x-data>
<!-- Global loading state -->
<p x-show="$gale.loading">Loading...</p>
<p x-show="$gale.error" x-text="$gale.error"></p>
<!-- Per-component loading state -->
<p x-show="$fetching">This component is fetching...</p>
<button @click="$postx('/save')" :disabled="$fetching">Save</button>
</div>
<div x-data>
<!-- Global loading state -->
<p x-show="$gale.loading">Loading...</p>
<p x-show="$gale.error" x-text="$gale.error"></p>
<!-- Per-component loading state -->
<p x-show="$fetching">This component is fetching...</p>
<button @click="$postx('/save')" :disabled="$fetching">Save</button>
</div>
Directives
x-navigate
SPA navigation for links, forms, and container elements.
| Modifier | Description |
|---|---|
.merge |
Keep current query params |
.only.param1.param2 |
Keep only specified query params |
.except.param1 |
Keep all except specified params |
.replace |
Replace history instead of push |
.key.name |
Navigation key for backend filtering |
.debounce.300ms |
Debounce navigation |
.throttle.500ms |
Throttle navigation |
<!-- Basic link navigation -->
<a href="/dashboard" x-navigate>Dashboard</a>
<!-- Merge query params -->
<a href="/search?q=test" x-navigate.merge>Search</a>
<!-- Form navigation -->
<form action="/search" x-navigate.debounce.300ms>
<input name="q" type="text">
</form>
<!-- Container with inherited navigation -->
<nav x-navigate.key.sidebar>
<a href="/page1">Page 1</a>
<a href="/page2">Page 2</a>
</nav>
<!-- Skip navigation for specific links -->
<a href="/external" x-navigate-skip>External</a>
Dashboard SearchExternal
x-component
Register a named component for backend targeting and cross-component access.
<!-- Register a named component -->
<div x-data="{ total: 0 }" x-component="cart">
<span x-text="total"></span>
</div>
<!-- With tags -->
<div x-data="{ items: [] }"
x-component="cart"
data-tags="shopping,header">
...
</div>
...
x-files
Mark file inputs for automatic inclusion in requests.
| Modifier | Description |
|---|---|
.max-size-5mb |
Maximum file size validation |
.max-files-3 |
Maximum number of files |
<!-- Basic file input -->
<input type="file" x-files="avatar">
<!-- With validation -->
<input type="file" x-files="document" x-files.max-size-10mb>
<!-- Multiple files -->
<input type="file" multiple x-files="photos" x-files.max-files-5>
<!-- Handle file errors -->
<input type="file" x-files="avatar"
:file-error="alert($event.detail.message)">
:file-error="alert($event.detail.message)">
x-message
Display validation messages from the server.
<!-- Single field error -->
<input type="email" x-model="email">
<div x-message="email" class="text-red-500"></div>
<!-- Multiple fields -->
<div x-message="email,name"></div>
<!-- Single field error --> <input type="email" x-model="email"> <div x-message="email" class="text-red-500"></div> <!-- Multiple fields --> <div x-message="email,name"></div>
x-loading
Show/hide elements or modify attributes during loading.
| Modifier | Description |
|---|---|
| (none) | Show element during loading |
.remove |
Hide element during loading |
.class="classes" |
Add classes during loading |
.class.remove="classes" |
Remove classes during loading |
.attr="name" |
Add attribute during loading |
.delay |
Delay showing by 200ms |
.delay.500ms |
Custom delay duration |
<!-- Show spinner during loading -->
<span x-loading>Loading...</span>
<!-- Hide content during loading -->
<div x-loading.remove>Content</div>
<!-- Add opacity class -->
<button x-loading.class="opacity-50 cursor-wait">Submit</button>
<!-- Disable during loading -->
<button x-loading.attr="disabled">Submit</button>
<!-- Delay showing (avoid flicker) -->
<span x-loading.delay>Loading...</span>
Loading...ContentLoading...
x-indicator
Bind loading state to an Alpine property for programmatic control.
<div x-data="{ isLoading: false }" x-indicator="isLoading">
<!-- Use isLoading in any expression -->
<p x-show="isLoading">Loading...</p>
<button :disabled="isLoading">Submit</button>
<div :class="isLoading ? 'blur-sm' : ''">Content</div>
</div>
<div x-data="{ isLoading: false }" x-indicator="isLoading">
<!-- Use isLoading in any expression -->
<p x-show="isLoading">Loading...</p>
<button :disabled="isLoading">Submit</button>
<div :class="isLoading ? 'blur-sm' : ''">Content</div>
</div>
x-poll
Automatic polling with configurable intervals.
| Modifier | Description |
|---|---|
.5s |
Poll every 5 seconds |
.500ms |
Poll every 500 milliseconds |
.visible |
Only poll when element is visible |
.csrf |
Include CSRF token |
<!-- Poll every 5 seconds -->
<div x-data="{ stats: {} }" x-poll.5s="/api/stats">
<p x-text="JSON.stringify(stats)"></p>
</div>
<!-- Only poll when visible -->
<div x-poll.2s.visible="/api/updates"></div>
<!-- With CSRF token -->
<div x-poll.5s.csrf="/api/protected"></div>
<!-- Conditional stop -->
<div x-data="{ status: 'pending' }"
x-poll.2s="/api/status"
x-poll-stop="status === 'complete'">
</div>
<!-- Poll every 5 seconds -->
<div x-data="{ stats: {} }" x-poll.5s="/api/stats">
<p x-text="JSON.stringify(stats)"></p>
</div>
<!-- Only poll when visible -->
<div x-poll.2s.visible="/api/updates"></div>
<!-- With CSRF token -->
<div x-poll.5s.csrf="/api/protected"></div>
<!-- Conditional stop -->
<div x-data="{ status: 'pending' }"
x-poll.2s="/api/status"
x-poll-stop="status === 'complete'">
</div>
x-confirm
Show confirmation dialog before actions.
<!-- Static message -->
<button x-confirm="Are you sure?" @click="$deletex('/item')">
Delete
</button>
<!-- Dynamic message -->
<button :x-confirm="`Delete ${name}?`" @click="$deletex('/item')">
Delete
</button>
Configuration APIs
Alpine Gale exposes configuration APIs on the Alpine.gale object.
CSRF Configuration
// Configure CSRF settings
Alpine.gale.configureCsrf({
headerName: 'X-CSRF-TOKEN', // HTTP header name
metaName: 'csrf-token' // Meta tag name
});
// Get current configuration
const config = Alpine.gale.getCsrfConfig();
// Configure CSRF settings
Alpine.gale.configureCsrf({
headerName: 'X-CSRF-TOKEN', // HTTP header name
metaName: 'csrf-token' // Meta tag name
});
// Get current configuration
const config = Alpine.gale.getCsrfConfig();
Navigation Configuration
// Configure navigation
Alpine.gale.configureNavigation({
interceptLinks: true, // Intercept link clicks
interceptForms: true, // Intercept form submissions
updateHistory: true, // Update browser history
defaultMode: 'push' // 'push' | 'replace'
});
// Get current configuration
const config = Alpine.gale.getNavigationConfig();
// Configure navigation
Alpine.gale.configureNavigation({
interceptLinks: true, // Intercept link clicks
interceptForms: true, // Intercept form submissions
updateHistory: true, // Update browser history
defaultMode: 'push' // 'push' | 'replace'
});
// Get current configuration
const config = Alpine.gale.getNavigationConfig();
Message Configuration
// Configure message display
Alpine.gale.configureMessage({
stateKey: 'messages' // State property for messages
});
// Get current configuration
const config = Alpine.gale.getMessageConfig();
// Configure message display
Alpine.gale.configureMessage({
stateKey: 'messages' // State property for messages
});
// Get current configuration
const config = Alpine.gale.getMessageConfig();
Confirm Configuration
// Custom confirm handler (e.g., SweetAlert)
Alpine.gale.configureConfirm(async (message) => {
const result = await Swal.fire({
title: 'Confirm',
text: message,
showCancelButton: true
});
return result.isConfirmed;
});
// Get current configuration
const handler = Alpine.gale.getConfirmConfig();
// Custom confirm handler (e.g., SweetAlert)
Alpine.gale.configureConfirm(async (message) => {
const result = await Swal.fire({
title: 'Confirm',
text: message,
showCancelButton: true
});
return result.isConfirmed;
});
// Get current configuration
const handler = Alpine.gale.getConfirmConfig();
Component Registry APIs
// Manual component registration
Alpine.gale.registerComponent(element, 'cart', ['shopping']);
Alpine.gale.unregisterComponent('cart');
// Component access
Alpine.gale.getComponent('cart');
Alpine.gale.getComponentsByTag('shopping');
Alpine.gale.hasComponent('cart');
Alpine.gale.getAllComponents();
// State management
Alpine.gale.updateComponentState('cart', { total: 99 });
Alpine.gale.invokeComponentMethod('cart', 'recalculate', 2.5);
// Lifecycle hooks
Alpine.gale.onComponentRegistered(({ name }) => console.log('Registered:', name));
Alpine.gale.onComponentUnregistered(({ name }) => console.log('Unregistered:', name));
Alpine.gale.onComponentStateChanged(({ name, updates }) => console.log('Changed:', name));
// Timing solutions
Alpine.gale.whenComponentReady('cart').then(c => console.log(c));
Alpine.gale.onComponentReady('cart', c => console.log(c));
// Reactive CRUD
Alpine.gale.getComponentState('cart');
Alpine.gale.createComponentState('cart', { items: [] });
Alpine.gale.deleteComponentState('cart', 'discount');
Alpine.gale.watchComponentState('cart', 'total', (val) => console.log(val));
// Manual component registration
Alpine.gale.registerComponent(element, 'cart', ['shopping']);
Alpine.gale.unregisterComponent('cart');
// Component access
Alpine.gale.getComponent('cart');
Alpine.gale.getComponentsByTag('shopping');
Alpine.gale.hasComponent('cart');
Alpine.gale.getAllComponents();
// State management
Alpine.gale.updateComponentState('cart', { total: 99 });
Alpine.gale.invokeComponentMethod('cart', 'recalculate', 2.5);
// Lifecycle hooks
Alpine.gale.onComponentRegistered(({ name }) => console.log('Registered:', name));
Alpine.gale.onComponentUnregistered(({ name }) => console.log('Unregistered:', name));
Alpine.gale.onComponentStateChanged(({ name, updates }) => console.log('Changed:', name));
// Timing solutions
Alpine.gale.whenComponentReady('cart').then(c => console.log(c));
Alpine.gale.onComponentReady('cart', c => console.log(c));
// Reactive CRUD
Alpine.gale.getComponentState('cart');
Alpine.gale.createComponentState('cart', { items: [] });
Alpine.gale.deleteComponentState('cart', 'discount');
Alpine.gale.watchComponentState('cart', 'total', (val) => console.log(val));
SSE Event Protocol
Alpine Gale processes these Server-Sent Events from the backend.
| Event | Description |
|---|---|
gale-patch-state |
Update Alpine state (RFC 7386 merge patch) |
gale-patch-elements |
Update DOM elements (morph, replace, etc.) |
gale-patch-component |
Update named component state |
gale-invoke-method |
Invoke method on named component |