spatie/laravel-pjax
Laravel middleware that detects PJAX (X-PJAX) requests and returns only the expected HTML fragments instead of full pages, enabling faster navigation with jquery-pjax. Simple composer install and add FilterIfPjax to your HTTP kernel.
Installation:
composer require spatie/laravel-pjax
Publish the config (optional):
php artisan vendor:publish --provider="Spatie\Pjax\PjaxServiceProvider" --tag="config"
Middleware Registration:
Add the middleware to your app/Http/Kernel.php in the $routeMiddleware array:
'pjax' => \Spatie\Pjax\Middleware\HandlePjaxRequests::class,
First Use Case:
Apply the middleware to a route (e.g., pjax prefix for PJAX-enabled routes):
Route::middleware('pjax')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
});
Client-Side Setup:
Include jQuery and PJAX in your layout (e.g., resources/views/layouts/app.blade.php):
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.pjax/2.0.1/jquery.pjax.min.js"></script>
<script>
$(document).pjax('a', '#pjax-container', {timeout: 5000});
</script>
Wrap your content in a container with an ID (e.g., pjax-container).
Route-Level PJAX: Apply the middleware to routes where PJAX is desired (e.g., admin dashboards, forms):
Route::middleware('pjax')->prefix('admin')->group(function () {
Route::resource('posts', PostController::class);
});
Conditional PJAX: Use the middleware conditionally in controllers:
public function __construct()
{
$this->middleware('pjax')->only(['index', 'store']);
}
Partial Responses:
Return partial views (e.g., _partials/dashboard.blade.php) for PJAX requests:
public function index()
{
if (request()->pjax) {
return view('partials.dashboard-content');
}
return view('dashboard');
}
Dynamic Container IDs:
Use a consistent container ID (e.g., pjax-container) or dynamically set it:
$(document).pjax('a[data-pjax]', '#' + $(this).data('pjax-container'));
Form Handling: Handle PJAX form submissions by returning partials for success/error responses:
public function store(Request $request)
{
$validated = $request->validate([...]);
if (request()->pjax) {
return view('partials.form-success', ['data' => $validated]);
}
return redirect()->back()->with('success', 'Submitted!');
}
Layout Overrides: Override the default layout for PJAX requests:
public function index()
{
if (request()->pjax) {
return view('partials.content', [], ['layout' => 'layouts.pjax']);
}
return view('page');
}
API + PJAX Hybrid: Combine PJAX with API responses for dynamic data:
$(document).on('pjax:complete', function() {
$.get('/api/data', function(data) {
$('#dynamic-data').html(data);
});
});
CSRF Token Mismatch: PJAX requests may fail due to missing CSRF tokens. Ensure tokens are included in partials:
@csrf
<input type="hidden" name="_token" value="{{ csrf_token() }}">
JavaScript Conflicts:
PJAX may interfere with event listeners or plugins. Use pjax:beforeSend/pjax:complete to reinitialize:
$(document).on('pjax:complete', function() {
$('[data-toggle="tooltip"]').tooltip();
});
Route Caching: Clear route cache if PJAX routes behave unexpectedly:
php artisan route:clear
Partial Caching: Avoid caching partials that rely on dynamic data (e.g., user-specific content).
History API Issues:
PJAX may break browser history. Use data-pjax attributes carefully:
<a href="/page" data-pjax>Load via PJAX</a>
Check Headers:
Verify X-PJAX header is present in responses:
if (request()->header('X-PJAX')) {
// PJAX request
}
Log PJAX Requests: Add middleware logging for debugging:
public function handle($request, Closure $next)
{
\Log::info('PJAX request detected', ['pjax' => request()->pjax]);
return $next($request);
}
Inspect Network Traffic: Use browser dev tools to verify AJAX responses match expected partials.
Custom Middleware: Extend the middleware to add logic (e.g., analytics):
public function handle($request, Closure $next)
{
if ($request->pjax) {
Analytics::track('pjax_request');
}
return $next($request);
}
Dynamic Container IDs: Override the default container ID in config:
'container_id' => 'dynamic-container',
PJAX Events: Listen for PJAX events in JavaScript:
$(document).on('pjax:start', function() { /* Show loader */ });
$(document).on('pjax:end', function() { /* Hide loader */ });
Vue/PJAX Integration: Use vue-pjax-adapter for Vue.js:
import VuePjax from 'vue-pjax-adapter';
Vue.use(VuePjax);
Server-Side Rendering (SSR):
Disable PJAX for SSR (e.g., Nuxt.js) by checking window.pjax:
if (window.pjax) {
// Enable PJAX
}
How can I help you explore Laravel packages today?