Request Detection
Detect Gale requests and respond differently based on request type.
Overview
Gale requests are identified by special HTTP headers. Detecting these allows you to:
- Return different responses for Gale vs regular HTTP requests
- Conditionally render Blade sections
- Handle navigation requests differently
- Build hybrid routes that work with and without JavaScript
How Gale Identifies Requests
When Alpine Gale makes a request, it sends a Gale-Request header. For navigation requests, it also sends Gale-Navigate and optionally Gale-Navigate-Key headers.
isGale()
The primary method to check if the current request is a Gale request:
1if (request()->isGale()) {
2 // This is a Gale SSE request
3 return gale()->state('updated', true);
4}
5
6// Regular HTTP request
7return view('page');
if (request()->isGale()) {
// This is a Gale SSE request
return gale()->state('updated', true);
}
// Regular HTTP request
return view('page');
isGaleNavigate()
Check if the request is a navigation request (triggered by x-navigate or $navigate()):
1// Check if it's any navigation request
2if (request()->isGaleNavigate()) {
3 // Handle navigation
4}
5
6// Check for a specific navigation key
7if (request()->isGaleNavigate('sidebar')) {
8 // Only update sidebar content
9}
10
11// Check for multiple possible keys
12if (request()->isGaleNavigate(['sidebar', 'content'])) {
13 // Handle either sidebar or content navigation
14}
// Check if it's any navigation request
if (request()->isGaleNavigate()) {
// Handle navigation
}
// Check for a specific navigation key
if (request()->isGaleNavigate('sidebar')) {
// Only update sidebar content
}
// Check for multiple possible keys
if (request()->isGaleNavigate(['sidebar', 'content'])) {
// Handle either sidebar or content navigation
}
Navigation Keys
galeNavigateKey() / galeNavigateKeys()
Get the raw navigation key(s) from the request:
1// Get the raw key string (e.g., "sidebar" or "sidebar,content")
2$keyString = request()->galeNavigateKey();
3
4// Get keys as an array
5$keys = request()->galeNavigateKeys();
6// ['sidebar', 'content']
// Get the raw key string (e.g., "sidebar" or "sidebar,content") $keyString = request()->galeNavigateKey(); // Get keys as an array $keys = request()->galeNavigateKeys(); // ['sidebar', 'content']
Blade Directive
Use @ifgale to conditionally render content in Blade templates:
1@ifgale
2
3 <div id="partial-content">
4 Updated content here
5 </div>
6@else
7
8 <!DOCTYPE html>
9 <html>
10 <head>...</head>
11 <body>
12 <div id="partial-content">
13 Initial content here
14 </div>
15 </body>
16 </html>
17@endifgale
<!DOCTYPE html>
<html>
<head>...</head>
<body>
<div id="partial-content">
Initial content here
</div>
</body>
</html>
This is useful for returning partial HTML for Gale requests while still supporting full page loads for direct URL visits or when JavaScript is disabled.
Conditional Response Methods
GaleResponse provides fluent methods for conditional execution:
whenGale()
1return gale()
2 ->whenGale(function ($gale) {
3 // Only executed for Gale requests
4 return $gale->state('partial', true);
5 }, function ($gale) {
6 // Fallback for non-Gale requests (optional)
7 return $gale->web(view('full-page'));
8 });
return gale()
->whenGale(function ($gale) {
// Only executed for Gale requests
return $gale->state('partial', true);
}, function ($gale) {
// Fallback for non-Gale requests (optional)
return $gale->web(view('full-page'));
});
whenNotGale()
1return gale()
2 ->state('data', $data)
3 ->whenNotGale(function ($gale) {
4 // Only for regular HTTP requests
5 return $gale->web(view('page'));
6 });
return gale()
->state('data', $data)
->whenNotGale(function ($gale) {
// Only for regular HTTP requests
return $gale->web(view('page'));
});
whenGaleNavigate()
1return gale()
2 ->whenGaleNavigate('sidebar', function ($gale) {
3 // Only when navigating with key 'sidebar'
4 return $gale->fragment('layouts.app', 'sidebar', $data);
5 })
6 ->whenGaleNavigate('content', function ($gale) {
7 // Only when navigating with key 'content'
8 return $gale->fragment('layouts.app', 'content', $data);
9 });
return gale()
->whenGaleNavigate('sidebar', function ($gale) {
// Only when navigating with key 'sidebar'
return $gale->fragment('layouts.app', 'sidebar', $data);
})
->whenGaleNavigate('content', function ($gale) {
// Only when navigating with key 'content'
return $gale->fragment('layouts.app', 'content', $data);
});
Practical Examples
Hybrid Route
A route that works for both Gale and regular requests:
1public function index()
2{
3 $posts = Post::latest()->paginate(10);
4
5 return gale()
6 ->state('posts', $posts->items())
7 ->state('pagination', [
8 'current' => $posts->currentPage(),
9 'total' => $posts->lastPage(),
10 ])
11 ->view('posts.list', compact('posts'), web: true);
12}
public function index()
{
$posts = Post::latest()->paginate(10);
return gale()
->state('posts', $posts->items())
->state('pagination', [
'current' => $posts->currentPage(),
'total' => $posts->lastPage(),
])
->view('posts.list', compact('posts'), web: true);
}
Tip
web: true option on view() automatically returns the view for non-Gale requests, eliminating the need for manual isGale() checks.
Partial Updates
Return only the changed portion for Gale requests:
1public function search(Request $request)
2{
3 $results = Product::search($request->state('query'))->get();
4
5 if (request()->isGale()) {
6 return gale()
7 ->state('results', $results)
8 ->fragment('products.index', 'results-list', compact('results'));
9 }
10
11 return view('products.index', compact('results'));
12}
public function search(Request $request)
{
$results = Product::search($request->state('query'))->get();
if (request()->isGale()) {
return gale()
->state('results', $results)
->fragment('products.index', 'results-list', compact('results'));
}
return view('products.index', compact('results'));
}
Split Navigation
Handle independent navigation regions:
1public function show(Category $category)
2{
3 $products = $category->products()->paginate(12);
4
5 // Sidebar navigation - only update sidebar
6 if (request()->isGaleNavigate('sidebar')) {
7 return gale()->fragment('shop.layout', 'sidebar', [
8 'categories' => Category::all(),
9 'active' => $category->id,
10 ]);
11 }
12
13 // Main content navigation
14 if (request()->isGaleNavigate('content')) {
15 return gale()
16 ->state('products', $products->items())
17 ->fragment('shop.layout', 'product-grid', compact('products'));
18 }
19
20 // Full page load
21 return view('shop.category', compact('category', 'products'));
22}
public function show(Category $category)
{
$products = $category->products()->paginate(12);
// Sidebar navigation - only update sidebar
if (request()->isGaleNavigate('sidebar')) {
return gale()->fragment('shop.layout', 'sidebar', [
'categories' => Category::all(),
'active' => $category->id,
]);
}
// Main content navigation
if (request()->isGaleNavigate('content')) {
return gale()
->state('products', $products->items())
->fragment('shop.layout', 'product-grid', compact('products'));
}
// Full page load
return view('shop.category', compact('category', 'products'));
}
Quick Reference
| Method/Directive | Description |
|---|---|
request()->isGale() |
Returns true for Gale requests |
request()->isGaleNavigate() |
Returns true for navigation requests |
request()->isGaleNavigate('key') |
Check for specific navigation key |
request()->galeNavigateKey() |
Get navigation key string |
request()->galeNavigateKeys() |
Get navigation keys as array |
@ifgale / @endifgale |
Blade conditional for Gale requests |
gale()->whenGale(cb, fallback) |
Execute callback for Gale requests |
gale()->whenNotGale(cb) |
Execute callback for non-Gale requests |
gale()->whenGaleNavigate(key, cb) |
Execute callback for specific navigation key |