yajra/laravel-datatables-editor
Laravel plugin for yajra/laravel-datatables that powers DataTables Editor (2.x) server-side CRUD in Laravel. Supports create/edit/remove actions and integrates with DataTables 2.x. Requires a DataTables Editor premium license.
Installation:
composer require yajra/laravel-datatables-editor:^13
Ensure yajra/laravel-datatables is also installed (required dependency).
Publish Config:
php artisan vendor:publish --provider="Yajra\DataTables\DataTablesServiceProvider" --tag=config
Generate Editor Controller:
php artisan datatables:editor User
Replace User with your Eloquent model. This creates a stub controller with CRUD methods.
Add Route:
// routes/web.php
Route::post('/users-editor', [UserEditor::class, 'index']);
Frontend Setup: Include DataTables Editor JS/CSS and initialize:
$(document).ready(function() {
$('#users-table').DataTable({
processing: true,
serverSide: true,
ajax: {
url: '/users-editor',
type: 'POST'
},
columns: [
{ data: 'id', name: 'id' },
{ data: 'name', name: 'name' },
{ data: 'email', name: 'email' }
],
editor: {
ajax: {
url: '/users-editor',
type: 'POST'
},
fields: [
{ label: 'ID', name: 'id' },
{ label: 'Name', name: 'name' },
{ label: 'Email', name: 'email' }
]
}
});
});
Inline Editing for a User Management Table:
UserEditor controller to handle CRUD operations for a users table.unique:users,email) to enforce data integrity.is_active for multiple users) via the Editor’s bulk actions.Controller Integration:
Extend Yajra\DataTables\DataTables and implement getEditor():
public function getEditor()
{
return $this->editor
->fields([
'id',
'name',
'email',
'is_active'
])
->create(function ($request) {
return User::create($request->all());
})
->update(function ($request, $key) {
$user = User::findOrFail($key);
$user->update($request->all());
return $user;
})
->delete(function ($key) {
$user = User::findOrFail($key);
return $user->delete();
});
}
Validation:
Use Laravel’s validation rules in validate():
protected function validate($request, $key = null, $rule = null)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,'.$key,
'is_active' => 'boolean'
]);
return $validator;
}
Event Hooks: Override pre/post events for custom logic:
protected function beforeCreate($request)
{
$request->merge(['created_by' => auth()->id()]);
}
protected function afterUpdate($request, $key)
{
event(new UserUpdated($key, $request->all()));
}
Bulk Operations:
Handle bulk edits/deletes in getEditor():
->edit(function ($request, $keys) {
return User::whereIn('id', $keys)->update(['is_active' => $request->is_active]);
})
->remove(function ($keys) {
return User::whereIn('id', $keys)->delete();
});
Artisan Commands:
Use php artisan datatables:editor to scaffold controllers for new models. Customize the stub template in resources/views/vendor/datatables/editor.blade.php.
Custom Actions:
Extend functionality with customActions:
->customActions([
'custom_action' => function ($request, $key) {
// Custom logic (e.g., send email, trigger API call)
return ['success' => true];
}
]);
Relationships:
Handle nested data (e.g., hasMany):
->fields([
'id',
'name',
'posts.*' // For nested data
]);
File Uploads: Use the built-in upload handlers:
protected function getUploadDirectory()
{
return 'uploads/users';
}
protected function storeUploadedFile($field, UploadedFile $uploadedFile)
{
return $uploadedFile->store($this->getUploadDirectory());
}
API Integration: Route Editor requests to a dedicated controller:
Route::post('/api/users-editor', [Api\UserEditor::class, 'index'])->middleware('api');
Testing: Mock Editor requests in PHPUnit/Pest:
$response = $this->post('/users-editor', [
'_token' => csrf_token(),
'action' => 'edit',
'data' => ['id' => 1, 'name' => 'Updated Name']
]);
Premium License Requirement:
CSRF Token Mismatch:
csrf_token() in your frontend or configure Laravel to trust the Editor’s AJAX origins:
// app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'users-editor',
];
SameSite cookies or stateless token validation.Validation Errors:
validate() method returns a Validator instance:
// ❌ Wrong
return ['error' => 'Validation failed'];
// ✅ Correct
return Validator::make($request->all(), $rules);
->errors() to format errors for Editor:
return response()->json(['errors' => $validator->errors()], 422);
Bulk Action Quirks:
{
"success": true,
"data": [...]
}
Log::info('Bulk edit response:', $response);
Model Binding:
findOrFail() or firstOrFail() to avoid silent failures:
// ❌ Risky
$user = User::find($key);
// ✅ Safe
$user = User::findOrFail($key);
Nested Data Conflicts:
posts.*) may cause conflicts if the backend expects a flat structure. Use ->fields() to explicitly define nested data:
->fields([
'id',
'name',
'posts.*.title', // Explicit nested field
'posts.*.content'
]);
Event Hook Timing:
beforeCreate) run before validation. Use post-events (e.g., afterCreate) for logic that depends on validated data.protected function beforeCreate($request) {
$request->merge(['temp_field' => 'value']);
}
protected function afterCreate($request) {
// Use $request->temp_field
}
Artisan Stub Customization:
datatables:editor command uses a stub template. Override it in resources/views/vendor/datatables/editor.blade.php to add custom methods or fields.customActions or upload handlers.Log Editor Requests: Add middleware to log raw Editor payloads:
// app/Http/Middleware/LogEditorRequests.php
public function handle($request, Closure $next) {
if ($request->isMethod('post') && $request->has('action')) {
Log::debug('Editor request:', $request->all());
}
return $next($request);
}
Validate Response Format: Use Postman or cURL to
How can I help you explore Laravel packages today?