Respons & error
Alat dan pola untuk menangani hasil submit form: redirect, flash, JSON, dan pengalaman pengguna.
NexaForm · redirect flash
Pengenalan
Penanganan response form yang tepat sangat penting untuk menciptakan user experience yang baik. NexaForm menyediakan sistem response yang komprehensif untuk menangani form submission, baik untuk traditional form maupun AJAX request.
Struktur Result dari process()
Method process() dari NexaForm mengembalikan array dengan struktur lengkap:
$result = $form->process();
// Struktur lengkap $result:
[
'success' => true|false, // Status validasi
'processed' => true|false, // Apakah form diproses (POST request)
'informasi' => 'data'|'file'|'tidak_ada_input', // Tipe input yang disubmit
'message' => 'Pesan sukses/error', // Pesan dari setSuccess()/setError()
'errors' => [], // Array error validasi (jika gagal)
'data' => [], // Data yang sudah divalidasi dan sanitize
'postData' => [], // Data POST original (sudah sanitize)
'files' => [], // Informasi file upload (jika ada)
'redirect' => '/url' // URL redirect (jika setRedirect() digunakan)
]Penjelasan Field Result:
- success:
truejika validasi berhasil,falsejika gagal - processed:
truejika form disubmit (POST request),falsejika GET - informasi: Tipe input yang disubmit
"data"- Hanya data form biasa"file"- Ada file upload (dengan atau tanpa data)"tidak_ada_input"- Tidak ada data yang disubmit
- message: Pesan yang di-set dengan
setSuccess()atausetError() - errors: Array error dengan format
['errors_fieldname' => 'Error message'] - data: Data yang sudah divalidasi dan sanitize (safe untuk database)
- postData: Data POST original yang sudah sanitize
- files: Informasi file yang diupload (jika ada upload)
- redirect: URL redirect (jika
setRedirect()digunakan)
Tipe Response
NexaForm mendukung multiple tipe response untuk form submission:
1. Response dengan Redirect
public function submitContact(): void
{
$form = $this->createForm();
$form->fields([
'name' => 'required|min:3',
'email' => 'required|email',
'message' => 'required|min:10'
])
->setSuccess('Pesan Anda berhasil dikirim!')
->setError('Terjadi kesalahan validasi');
$result = $form->process();
if ($result['success']) {
// Simpan ke database
$this->useModels('Contact', 'save', $result['data']);
// Set flash message dan redirect
$this->setFlash('success', $result['message']);
$this->redirect('/contact/thank-you');
} else {
// Redirect kembali dengan error
$this->setFlash('error', $result['message']);
$this->redirect('/contact');
}
}2. Response JSON (untuk AJAX)
public function submitAjax(): void
{
$form = $this->createForm();
$form->fields([
'name' => 'required|min:3',
'email' => 'required|email'
])
->setAjax(true) // ← Aktifkan mode AJAX
->setSuccess('Data berhasil disimpan!')
->setError('Terjadi kesalahan validasi');
// Process akan otomatis return JSON dan exit jika AJAX
$result = $form->process();
// Code di bawah hanya dijalankan jika bukan AJAX
if ($result['success']) {
$this->redirect('/success');
}
}
// Response JSON otomatis:
// {
// "success": true,
// "processed": true,
// "informasi": "data",
// "message": "Data berhasil disimpan!",
// "data": {"name": "John", "email": "john@example.com"},
// "errors": []
// }3. Response ke Template (Same-Page)
public function contactForm(): void
{
$form = $this->createForm();
$form->fields([
'name' => 'required|min:3',
'email' => 'required|email',
'message' => 'required|min:10'
])
->setSuccess('Pesan berhasil dikirim!')
->setError('Silakan perbaiki error di bawah');
if ($this->isPost()) {
$result = $form->process();
if ($result['success']) {
// Simpan data
$this->useModels('Contact', 'save', $result['data']);
// Assign dengan clearValues = true untuk reset form
$this->assignVars($form->Response([], true));
} else {
// Assign dengan error dan data untuk repopulate
$this->assignVars($form->Response());
}
} else {
// GET request, tampilkan form kosong
$this->assignVars($form->Response());
}
$this->render('contact/form');
}$clearValues untuk reset form setelah sukses.
Method Response() untuk Template
Method Response() menghasilkan data yang siap digunakan di template:
// Mendapatkan data untuk template
$templateData = $form->Response();
// Atau dengan data tambahan
$templateData = $form->Response([
'categories' => $this->useModels('Category', 'getAll'),
'tags' => $this->useModels('Tag', 'getAll')
]);
// Atau reset form setelah sukses (clearValues = true)
$templateData = $form->Response([], true);
// Struktur $templateData:
[
// Field values (untuk repopulate form)
'name' => 'John Doe',
'name_value' => 'John Doe', // Alias
'email' => 'john@example.com',
'email_value' => 'john@example.com',
// Error messages per field
'errors_name' => '',
'errors_email' => 'Format email tidak valid',
// Info message (sukses atau error)
'info_message' => 'Terjadi kesalahan validasi',
// File info (jika ada field file)
'image_info' => '<small>File berhasil dipilih: "photo.jpg"</small>',
// Data tambahan yang di-merge
'categories' => [...],
'tags' => [...]
]Penggunaan di Template
<!-- Tampilkan info message -->
<form method="post">
<div class="form-group">
<label for="name">Nama</label>
<input type="text" name="name" value="{name}" class="form-control">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" value="" class="form-control">
</div>
<button type="submit">Kirim</button>
</form>Flash Messages dengan NexaSession
Untuk redirect response, gunakan flash message dari NexaSession:
// Setting flash messages
public function processForm(): void
{
// Process form...
// Set flash message before redirect
$this->setFlashMessage('success', 'Your profile has been updated!');
$this->redirect('/profile');
}In your template, you can display flash messages like this:
<!-- In your template file -->
<?php if ($this->hasFlashMessage()): ?>
<div class="alert alert-<?= $this->getFlashMessageType() ?>">
<?= $this->getFlashMessage() ?>
</div>
<?php endif; ?>Flash messages are stored in the session and automatically cleared after being displayed once.
Handling Validation Errors
When form validation fails, NexaUI provides methods to handle and display errors:
// Controller method
public function processForm(): void
{
$formData = $this->getPostData();
// Validate form data
$validator = new NexaValidator();
$validator->rule('required', ['name', 'email', 'message']);
$validator->rule('email', 'email');
if ($validator->validate($formData)) {
// Process valid form data
$this->processValidForm($formData);
} else {
// Handle validation errors
$this->assignVars([
'formErrors' => $validator->errors(),
'formData' => $formData // To repopulate the form
]);
// Re-render the form
$this->render('contact-form');
}
}In your template, display validation errors:
<form method="post" action="/contact">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name"
value="<?= $this->escape($formData['name'] ?? '') ?>">
<?php if (isset($formErrors['name'])): ?>
<div class="error-message"><?= $this->escape($formErrors['name'][0]) ?></div>
<?php endif; ?>
</div>
<!-- Similar for other fields -->
<button type="submit">Submit</button>
</form>Form Repopulation
When validation fails, it's important to repopulate the form with the user's previous input:
// In your controller
public function showForm(): void
{
// Get old input data from session (if any)
$oldInput = $this->getOldInput();
$this->assignVars([
'formData' => $oldInput
]);
$this->render('form-page');
}
public function processForm(): void
{
$formData = $this->getPostData();
// Validate form data
$isValid = $this->validateFormData($formData);
if (!$isValid) {
// Save input to session
$this->saveInputToSession($formData);
// Redirect back to form
$this->redirect('/form');
}
// Process valid form...
}
private function saveInputToSession(array $input): void
{
$_SESSION['old_input'] = $input;
}
private function getOldInput(): array
{
$oldInput = $_SESSION['old_input'] ?? [];
// Clear old input after retrieving
unset($_SESSION['old_input']);
return $oldInput;
}Response Helper Methods
NexaUI provides several helper methods for common response patterns:
Success Response
public function successResponse($data = null, string $message = 'Operation successful'): void
{
if ($this->isAjaxRequest()) {
$this->sendJsonResponse([
'success' => true,
'message' => $message,
'data' => $data
]);
} else {
$this->setFlashMessage('success', $message);
$this->redirect($this->getReferer() ?? '/');
}
}Error Response
public function errorResponse(string $message = 'An error occurred', $errors = null): void
{
if ($this->isAjaxRequest()) {
$this->sendJsonResponse([
'success' => false,
'message' => $message,
'errors' => $errors
]);
} else {
$this->setFlashMessage('error', $message);
$this->redirect($this->getReferer() ?? '/');
}
}Validation Error Response
public function validationErrorResponse(array $errors, string $message = 'Please correct the errors below'): void
{
if ($this->isAjaxRequest()) {
$this->sendJsonResponse([
'success' => false,
'message' => $message,
'errors' => $errors
]);
} else {
$this->saveInputToSession($this->getPostData());
$this->saveErrorsToSession($errors);
$this->setFlashMessage('error', $message);
$this->redirect($this->getReferer() ?? '/');
}
}Response Formatting
For consistent response formatting, NexaUI provides standardized response structures:
JSON Response Format
{
"success": true|false,
"message": "Human-readable message",
"data": {
// Optional data payload
},
"errors": {
// Optional validation errors
"field_name": ["Error message"]
},
"meta": {
// Optional metadata
"pagination": {
"total": 100,
"per_page": 10,
"current_page": 1,
"last_page": 10
}
}
}HTML Response Format
For HTML responses, NexaUI provides a consistent structure for displaying messages:
<!-- Success message -->
<div class="alert alert-success">
<i class="icon-check"></i>
<span>Form submitted successfully!</span>
</div>
<!-- Error message -->
<div class="alert alert-danger">
<i class="icon-warning"></i>
<span>There was a problem processing your form.</span>
</div>
<!-- Field-level errors -->
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" class="has-error">
<div class="field-error">Please enter a valid email address.</div>
</div>Best Practices
- Always provide clear, user-friendly error messages
- Repopulate form fields with previous input when validation fails
- Use consistent response formats for both AJAX and traditional form submissions
- Include both general form messages and field-specific error messages
- Use flash messages for one-time notifications after redirects
- Always sanitize and validate data on the server side, regardless of client-side validation
- For security-sensitive forms, consider implementing CSRF protection
- Group related form fields in the response for better organization
Complete Example
Here's a complete example of form processing with response handling:
Controller:
class ContactController extends NexaController
{
public function showForm(): void
{
// Get old input and errors from session (if any)
$oldInput = $this->getOldInput();
$errors = $this->getOldErrors();
$this->assignVars([
'formData' => $oldInput,
'formErrors' => $errors
]);
$this->render('contact/form');
}
public function processForm(): void
{
$formData = $this->getPostData();
// Validate form data
$validator = new NexaValidator();
$validator->rule('required', ['name', 'email', 'message']);
$validator->rule('email', 'email');
if (!$validator->validate($formData)) {
// Handle validation errors
$this->validationErrorResponse(
$validator->errors(),
'Please correct the errors in your form.'
);
return;
}
// Process the form (e.g., send email)
$success = $this->sendContactEmail(
$formData['name'],
$formData['email'],
$formData['message']
);
if ($success) {
$this->successResponse(
null,
'Thank you for your message. We will get back to you soon.'
);
} else {
$this->errorResponse(
'Failed to send your message. Please try again later.'
);
}
}
private function sendContactEmail(string $name, string $email, string $message): bool
{
// Implementation of email sending logic
// ...
return true; // or false if failed
}
}Template (contact/form.php):
<!-- Display flash messages if any -->
<?php if ($this->hasFlashMessage()): ?>
<div class="alert alert-<?= $this->getFlashMessageType() ?>">
<?= $this->getFlashMessage() ?>
</div>
<?php endif; ?>
<form method="post" action="/contact/submit">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name"
value="<?= $this->escape($formData['name'] ?? '') ?>"
class="<?= isset($formErrors['name']) ? 'has-error' : '' ?>">
<?php if (isset($formErrors['name'])): ?>
<div class="field-error"><?= $this->escape($formErrors['name'][0]) ?></div>
<?php endif; ?>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email"
value="<?= $this->escape($formData['email'] ?? '') ?>"
class="<?= isset($formErrors['email']) ? 'has-error' : '' ?>">
<?php if (isset($formErrors['email'])): ?>
<div class="field-error"><?= $this->escape($formErrors['email'][0]) ?></div>
<?php endif; ?>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea id="message" name="message"
class="<?= isset($formErrors['message']) ? 'has-error' : '' ?>"><?= $this->escape($formData['message'] ?? '') ?></textarea>
<?php if (isset($formErrors['message'])): ?>
<div class="field-error"><?= $this->escape($formErrors['message'][0]) ?></div>
<?php endif; ?>
</div>
<button type="submit" class="btn btn-primary">Send Message</button>
</form>Lanjut
Sebelumnya: Keamanan form. Berikutnya: Form AJAX. Indeks Forms · Dokumentasi · Beranda.