yajra/laravel-datatables-editor
Laravel plugin for yajra/laravel-datatables that handles server-side processing for DataTables Editor 2.x. Provides CRUD actions, validation, and Laravel 12.x integration for Editor-powered DataTables (premium Editor license required).
composer require yajra/laravel-datatables-editor:^13
npm install datatables.net-dt
npm install @datatables.net-editor
User):
php artisan datatables:editor User
This creates a controller (UserEditorController) with pre-configured CRUD methods.$(document).ready(function() {
$('#user-table').DataTable({
processing: true,
serverSide: true,
ajax: '/users-editor',
columns: [
{ data: 'id', name: 'id' },
{ data: 'name', name: 'name' },
{ data: 'email', name: 'email' },
{
data: null,
name: 'action',
orderable: false,
searchable: false,
render: function(data, type, row) {
return `<a href="#" class="edit-row" data-id="${row.id}">Edit</a>`;
}
}
],
dom: 'lrtip',
buttons: [
{ extend: 'editor', editor: {
ajax: {
newAction: '/users-editor/create',
editAction: '/users-editor/update',
removeAction: '/users-editor/destroy'
},
fields: [
{ label: 'Name:', name: 'name' },
{ label: 'Email:', name: 'email' }
]
}}
]
});
});
UserEditorController):
public function anyDataTable()
{
return $this->datatables
->eloquent($this->query())
->make(true);
}
create, update, and destroy methods in the generated controller:
public function anyCreate()
{
return $this->editor->create();
}
public function anyUpdate()
{
return $this->editor->update();
}
public function anyDestroy()
{
return $this->editor->destroy();
}
bulk method for mass updates/deletes:
public function anyBulk()
{
return $this->editor->bulk();
}
getRules() method of your editor controller:
protected function getRules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,'.$this->getKey().',id',
];
}
validate() for complex logic:
protected function validate($request)
{
$validator = Validator::make($request->all(), $this->getRules());
if ($validator->fails()) {
return $this->editor->jsonResponse($validator->errors()->all(), 422);
}
return true;
}
protected function beforeCreate($request)
{
// Example: Log creation
\Log::info('User created via DataTables Editor', $request->all());
}
protected function afterUpdate($request, $model)
{
// Example: Send email
Mail::to($model->email)->send(new UserUpdated($model));
}
protected function afterSave($request, $model)
{
event(new UserSaved($model));
}
customActions:
protected function getCustomActions()
{
return [
'custom_action' => [
'label' => 'Custom Action',
'action' => 'customAction',
'buttonClass' => 'btn btn-warning',
],
];
}
public function customAction()
{
$data = $this->editor->getData();
// Custom logic (e.g., API call, file processing)
return $this->editor->jsonResponse(['success' => true]);
}
storeUploadedFile:
protected function storeUploadedFile($field, UploadedFile $uploadedFile)
{
$path = $uploadedFile->store('uploads', $this->getDisk());
return $path;
}
protected function getUploadDirectory()
{
return 'uploads';
}
protected function getDisk()
{
return \Storage::disk('public');
}
Route::prefix('users-editor')->group(function () {
Route::any('/', [UserEditorController::class, 'anyDataTable']);
Route::any('create', [UserEditorController::class, 'anyCreate']);
Route::any('update', [UserEditorController::class, 'anyUpdate']);
Route::any('destroy', [UserEditorController::class, 'anyDestroy']);
Route::any('bulk', [UserEditorController::class, 'anyBulk']);
});
<table id="user-table" class="display" style="width:100%">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
</table>
public function test_create_user_via_editor()
{
$response = $this->postJson('/users-editor/create', [
'name' => 'Test User',
'email' => 'test@example.com',
]);
$response->assertStatus(200);
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
}
Premium License Requirement:
CSRF Token Mismatch:
CSRF token mismatch if not handled properly.VerifyCsrfToken middleware:
protected $except = [
'users-editor/*',
];
meta data in Editor initialization:
editor: {
meta: {
csrf_token: '{{ csrf_token() }}'
}
}
Model Key Conflicts:
id, override getKey():
protected function getKey()
{
return $this->editor->getModel()->getKeyName();
}
Bulk Action Validation:
public function anyBulk()
{
$response = $this->editor->bulk();
if ($response->hasErrors()) {
return $this->editor->jsonResponse([
'error' => 'Some records failed to update',
'errors' => $response->getErrors()
], 422);
}
return $response;
}
Nested Relations:
hasMany). Use custom fields or server-side processing:
fields: [
{
label: 'Orders:',
name: 'orders',
type: 'select',
options: {
url: '/orders-dropdown',
cache: true
}
}
]
Type Safety:
Yajra\DataTables\Editor\Editor and methods are typed:
public function anyDataTable(): JsonResponse
{
return $this->datatables->eloquent($this->query())->make(true);
}
How can I help you explore Laravel packages today?