Pre-Confirm & Pre-Deny Routes
The pre-confirm and pre-deny route patterns are among the most powerful features in v8. They allow you to validate user input on the server side before the SweetAlert2 dialog closes, providing real-time feedback without writing any JavaScript.
Pre-Confirm Route
How It Works
- You configure an input alert with
preConfirmRoute(), passing a Laravel route URL - When the user clicks the confirm button, SweetAlert2 sends an AJAX POST request to that route with the input value
- Your route handler validates the input and returns a JSON response
- If validation passes (
"valid": true), the dialog closes normally - If validation fails (
"valid": false), the error message is displayed inline and the dialog stays open
Basic Usage
use RealRashid\SweetAlert\Facades\Alert;
use RealRashid\SweetAlert\Enums\InputType;
Alert::input('Enter promo code', InputType::Text)
->preConfirmRoute(route('validate-promo'))
->showLoaderOnConfirm()
->flash();Route Handler
Create a route that accepts POST requests and returns a JSON response:
// routes/web.php
Route::post('/validate-promo', [PromoController::class, 'validateCode'])
->name('validate-promo');// app/Http/Controllers/PromoController.php
public function validateCode(Request $request)
{
$code = $request->input('value');
$promo = PromoCode::where('code', $code)->first();
if (! $promo) {
return response()->json([
'valid' => false,
'message' => 'This promo code does not exist.',
]);
}
if ($promo->isExpired()) {
return response()->json([
'valid' => false,
'message' => 'This promo code has expired.',
]);
}
return response()->json([
'valid' => true,
'code' => $promo->code,
'discount' => $promo->discount_percentage,
]);
}Response Format
Success Response
When validation passes, return a JSON object with "valid": true. You can include additional data that will be available in the result.value of the SweetAlert2 promise:
return response()->json([
'valid' => true,
'id' => $model->id,
'name' => $model->name,
]);Failure Response
When validation fails, return a JSON object with "valid": false and a message key containing the error text:
return response()->json([
'valid' => false,
'message' => 'The entered value is invalid.',
]);Show Loader on Confirm
Always pair preConfirmRoute() with showLoaderOnConfirm() to give the user visual feedback while the AJAX request is in progress:
Alert::input('Enter verification code', InputType::Text)
->preConfirmRoute(route('verify-code'))
->showLoaderOnConfirm()
->flash();The confirm button will show a spinning loader while waiting for the server response.
CSRF Protection
The pre-confirm AJAX request automatically includes the Laravel CSRF token. The Blade view injects it via {{ csrf_token() }}, so you don't need to handle CSRF manually.
Request Format
The pre-confirm route receives a POST request with:
- Header:
Content-Type: application/json - Header:
X-CSRF-TOKEN: The Laravel CSRF token - Header:
Accept:application/json - Body:
{ "value": "user_input_here" }
The value key contains whatever the user entered in the input field.
Advanced Examples
Email Subscription Validation
Alert::input('Subscribe to newsletter', InputType::Email)
->inputPlaceholder('you@example.com')
->preConfirmRoute(route('newsletter.validate'))
->showLoaderOnConfirm()
->confirmButton('Subscribe', '#28a745')
->flash();// Controller
public function validateEmail(Request $request)
{
$email = $request->input('value');
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
return response()->json([
'valid' => false,
'message' => 'Please enter a valid email address.',
]);
}
if (Subscriber::where('email', $email)->exists()) {
return response()->json([
'valid' => false,
'message' => 'This email is already subscribed.',
]);
}
Subscriber::create(['email' => $email]);
return response()->json([
'valid' => true,
'email' => $email,
]);
}Username Availability Check
Alert::input('Choose a username', InputType::Text)
->inputPlaceholder('johndoe')
->inputAutoTrim(true)
->inputAttributes(['maxlength' => 20, 'pattern' => '[a-zA-Z0-9_]+'])
->preConfirmRoute(route('username.check'))
->showLoaderOnConfirm()
->flash();Delete Confirmation with Server Check
Alert::confirmDelete('Delete this order?')
->preConfirmRoute(route('orders.can-delete', $order))
->flash();This pattern checks whether the order can be deleted (e.g., it hasn't been shipped yet) before allowing the deletion.
Without Input
You can also use preConfirmRoute() on non-input alerts. The value in the request body will be null, but you can still use the route for server-side checks:
Alert::title('Publish this article?')
->question()
->preConfirmRoute(route('articles.can-publish', $article))
->showLoaderOnConfirm()
->flash();Under the Hood
The Blade view renders the pre-confirm route as JavaScript:
swalConfig.preConfirm = function(value) {
return fetch(preConfirmRoute, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken,
'Accept': 'application/json'
},
body: JSON.stringify({ value: value })
})
.then(function(response) { return response.json(); })
.then(function(data) {
if (data.valid === false) {
Swal.showValidationMessage(data.message || 'Validation failed');
}
return data;
})
.catch(function() {
Swal.showValidationMessage('Request failed');
});
};No manual JavaScript is required — everything is handled by the Blade template.
Pre-Deny Route
The preDenyRoute() method mirrors preConfirmRoute() but fires when the user clicks the deny button. This is useful for two-action dialogs where both confirm and deny need server-side validation.
How It Works
- You configure an alert with a deny button and
preDenyRoute(), passing a Laravel route URL - When the user clicks the deny button, SweetAlert2 sends an AJAX POST request to that route
- Your route handler processes the denial and returns a JSON response
- If
"valid": true, the dialog closes with the deny result - If
"valid": false, the error message is displayed inline and the dialog stays open
Basic Usage
use RealRashid\SweetAlert\Facades\Alert;
Alert::title('Review submission')
->question()
->confirmButton('Approve')
->denyButton('Reject')
->preDenyRoute(route('reviews.reject', $review))
->flash();Route Handler
// routes/web.php
Route::post('/reviews/{review}/reject', [ReviewController::class, 'reject'])
->name('reviews.reject');// app/Http/Controllers/ReviewController.php
public function reject(Request $request, Review $review)
{
if ($review->isPublished()) {
return response()->json([
'valid' => false,
'message' => 'Published reviews cannot be rejected.',
]);
}
$review->update(['status' => 'rejected']);
return response()->json(['valid' => true]);
}Combining preConfirmRoute and preDenyRoute
You can use both on the same alert for full two-action server-side validation:
Alert::title('Approve or reject this order?')
->question()
->confirmButton('Approve', '#28a745')
->denyButton('Reject', '#dc3545')
->preConfirmRoute(route('orders.approve', $order))
->preDenyRoute(route('orders.reject', $order))
->showLoaderOnConfirm()
->flash();Under the Hood
The Blade view renders the pre-deny route as JavaScript, mirroring the pre-confirm pattern:
swalConfig.preDeny = function(value) {
return fetch(preDenyRoute, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken,
'Accept': 'application/json'
},
body: JSON.stringify({ value: value })
})
.then(function(response) { return response.json(); })
.then(function(data) {
if (data.valid === false) {
Swal.showValidationMessage(data.message || 'Validation failed');
}
return data;
})
.catch(function() {
Swal.showValidationMessage('Request failed');
});
};