yajra/laravel-datatables-editor
Laravel DataTables Editor plugin for Laravel DataTables: server-side processing for DataTables Editor 2.x CRUD (create, edit, remove) with Laravel 12.x support. Requires a DataTables Editor premium license.
Install the Package
composer require yajra/laravel-datatables-editor:^13
Ensure yajra/laravel-datatables is also installed (required dependency).
Publish Configuration (Optional)
php artisan vendor:publish --provider="Yajra\DataTables\DataTablesServiceProvider" --tag=config
Customize editor settings in config/datatables.php.
Generate a Basic Editor Controller Use the Artisan command to scaffold a controller:
php artisan datatables:editor User
This creates a UserEditor controller with CRUD methods pre-configured for the User model.
Define Routes
Add routes in routes/web.php:
Route::resource('users', UserController::class);
Route::post('users/editor', [UserEditor::class, 'index'])->name('users.editor');
Integrate Frontend Include DataTables Editor JS/CSS and initialize the editor:
<script src="https://cdn.datatables.net/editor/2.x/js/dataTables.editor.min.js"></script>
<script>
$(document).ready(function() {
$('#users-table').DataTable({
processing: true,
serverSide: true,
ajax: '{{ route("users.editor") }}',
columns: [
{ data: 'id', name: 'id' },
{ data: 'name', name: 'name' },
{ data: 'email', name: 'email' },
],
editUrl: '{{ route("users.editor") }}',
edit: {
url: '{{ route("users.editor") }}',
mode: 'inline'
}
});
});
</script>
Generate the Editor Controller
Run the Artisan command for your model (e.g., User):
php artisan datatables:editor User
This generates a controller with methods like getModel(), getColumns(), and getEditor().
Customize Columns and Editor Fields
Override getColumns() and getEditor() in UserEditor:
public function getColumns(): array
{
return [
['data' => 'id', 'name' => 'id'],
['data' => 'name', 'name' => 'name'],
['data' => 'email', 'name' => 'email'],
['data' => 'is_active', 'name' => 'is_active'],
];
}
public function getEditor(): array
{
return [
'id' => [
'source' => 'db',
'label' => 'ID',
'order' => 1,
],
'name' => [
'source' => 'db',
'label' => 'Name',
'order' => 2,
],
'email' => [
'source' => 'db',
'label' => 'Email',
'order' => 3,
'validator' => [
'regex' => '/^[^\s@]+@[^\s@]+\.[^\s@]+$/',
'message' => 'Invalid email format',
],
],
'is_active' => [
'source' => 'db',
'label' => 'Active',
'order' => 4,
'type' => 'checkbox',
],
];
}
Test Inline Editing
Visit your table page (e.g., /users). Click on a cell to edit, save changes, and verify the backend updates via Laravel’s query log or database inspection.
UserEditor for method signatures and default implementations.getEditor() and getColumns() methods to define editable fields and table structure.php artisan datatables:editor to generate boilerplate for new models.preCreate(), postUpdate(), etc., in the generated controller for custom logic.Use the generated controller as a starting point:
// UserEditor.php
protected function getModel(): string
{
return User::class;
}
public function getColumns(): array
{
return [
['data' => 'id', 'name' => 'id'],
['data' => 'name', 'name' => 'name'],
// Add more columns as needed
];
}
public function getEditor(): array
{
return [
'name' => [
'source' => 'db',
'label' => 'Full Name',
'order' => 1,
],
'email' => [
'source' => 'db',
'label' => 'Email',
'order' => 2,
'validator' => ['required'],
],
];
}
Enable bulk editing/deleting by configuring the frontend:
$('#users-table').DataTable({
// ... other config
edit: {
url: '{{ route("users.editor") }}',
mode: 'inline',
buttons: {
edit: {
extend: 'edit',
editor: {
actions: {
edit: true,
remove: true,
create: true
}
}
}
}
}
});
Leverage Laravel’s validation rules in the getEditor() method:
public function getEditor(): array
{
return [
'email' => [
'source' => 'db',
'label' => 'Email',
'validator' => [
'required',
'email',
'unique:users,email,{{id}}',
],
],
'password' => [
'source' => 'db',
'label' => 'Password',
'validator' => [
'required_if:is_new,true',
'min:8',
'confirmed',
],
],
];
}
Extend the controller with pre/post hooks for custom logic:
protected function preCreate($model, $data): void
{
$model->created_by = auth()->id();
$model->updated_by = auth()->id();
}
protected function postUpdate($model, $data): void
{
event(new UserUpdated($model, $data));
}
Add custom actions (e.g., file uploads, API calls) via customActions:
public function getEditor(): array
{
return [
'avatar' => [
'source' => 'db',
'label' => 'Avatar',
'type' => 'file',
'upload' => [
'url' => route('users.upload-avatar'),
'method' => 'POST',
'accept' => 'image/*',
],
],
];
}
Use the Editor as Route Action feature (v12.3.0+) to handle Editor requests via routes:
Route::post('/users/editor', [UserEditor::class, 'process'])->name('users.editor');
Override process() to handle custom logic:
public function process(Request $request)
{
return $this->editor->process($request);
}
Handle file uploads in a custom method:
protected function storeUploadedFile($field, UploadedFile $uploadedFile)
{
$path = $uploadedFile->store('avatars', 'public');
return '/storage/' . $path;
}
Fetch columns dynamically based on user roles:
public function getColumns(): array
{
if (auth()->user()->isAdmin()) {
return [
['data' => 'id', 'name' => 'id'],
['data' => 'name', 'name' => 'name'],
['data' => 'email', 'name' => 'email'],
['data' => 'created_at', 'name' => 'created_at'],
];
}
return [
['data' => 'name', 'name' => 'name'],
['data' => 'email', 'name' => 'email'],
];
}
Test Editor endpoints with Pest/PHPUnit:
public function test_editor_create_user()
{
$response = $this->postJson(route('users.editor'), [
'data' => [
'name' => 'Test User',
'email' => 'test@example.com',
],
]);
$response->assertCreated();
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
}
How can I help you explore Laravel packages today?