This package adds a few editable columns for projects that use Backpack for Laravel v6:
editable_text
editable_checkbox
editable_switch
editable_select
When edited, those columns will submit an AJAX request to the controller, so that attribute is updated in the database. The developer is in complete control of the saving process, to make these column as versatile as possible:
For the editable_text
column, as an admin, you'll notice that:
Enter
saves the valueEsc
reverts the changes↑
(up arrow) moves one row up (same editable column)↓
(down arrow) moves one row down (same editable column)Tab
moves to the next editable inputShift
+ Tab
moves to the previous editable inputFor the editable_select
:
save_on_change
to false
(it will save on only on focus out)editable_select
is the same as for the editable_text
(Enter
, Esc
, ↑
, ↓
, Tab
, Shift
+ Tab
)
Space
or Enter
opens the dropdownoptions
attribute to provide the options of the select input, you can directly pass an array or, you can use a closure, in the closure you'll have the entry as an argument (check the examples bellow)."select_from_ajax"
you can enable the forceReloadAfterUpdate
that will redraw the table on update and update the select options given the current entry state. Eg. CRUD::setOperationSetting('forceReloadAfterUpdate', true)
in your setupListOperation()
For the editable_checkbox
and editable_switch
columns, as an admin... you'll notice that it "just works".
Don't believe how simple it is to use? Go ahead, try it right now, in our online demo.
In your Laravel + Backpack project, run:
php artisan backpack:require:editablecolumns
It will ask you for your token & password - which you get after you purchase this package. If you've purchased previously, you can see your token and password in your Backpack account.
Alternatively, if the quick installation above doesn't work, you can follow the steps below:
Step 1. Buy access to this package and you'll get an access token. With that token in hand, you should instruct your project to pull in missing packages from our private repository, instead of Packagist:
auth.json
file by running composer config http-basic.backpackforlaravel.com [your-token-username] [your-token-password]
composer.json
:"repositories": [
{
"type": "composer",
"url": "https://repo.backpackforlaravel.com/"
}
],
Step 2. In your project, via command line:
composer require backpack/editable-columns
Step 1. Inside your ProductCrudController (for example), use this new operation we've provided:
class ProductCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
+ use \Backpack\EditableColumns\Http\Controllers\Operations\MinorUpdateOperation;
public function setup()
{
CRUD::setModel(\App\Models\Product::class);
CRUD::setRoute(config('backpack.base.route_prefix').'/product');
CRUD::setEntityNameStrings('product', 'products');
}
Step 2. In your ListOperation, instead of using text
, number
, check
, select_from_array
columns, use the columns this package provides, if you want them editable:
public function setupListOperation()
{
// editable_text
CRUD::addColumn([
'name' => 'price',
'type' => 'editable_text',
'label' => 'Price',
// Optionals
'underlined' => true, // show a dotted line under the editable column for differentiation? default: true
'min_width' => '120px', // how wide should the column be?
'select_on_click' => false, // select the entire text on click? default: false
'save_on_focusout' => false, // if user clicks out, the value should be saved (instead of greyed out)
'on_error' => [
'text_color' => '#df4759', // set a custom text color instead of the red
'text_color_duration' => 0, // how long (in milliseconds) should the text stay that color (0 for infinite, aka until page refresh)
'text_value_undo' => false, // set text to the original value (user will lose the value that was recently input)
],
'on_success' => [
'text_color' => '#42ba96', // set a custom text color instead of the green
'text_color_duration' => 3000, // how long (in milliseconds) should the text stay that color (0 for infinite, aka until page refresh)
],
'auto_update_row' => true, // update related columns in same row, after the AJAX call?
]);
// editable_checkbox
CRUD::addColumn([
'name' => 'agreed',
'label' => 'Agreed',
'type' => 'editable_checkbox',
// Optionals
'underlined' => true, // show a dotted line under the editable column for differentiation? default: true
'on_error' => [
'status_color' => '#df4759', // set a custom text color instead of the red
'status_color_duration' => 0, // how long (in milliseconds) should the text stay that color (0 for infinite, aka until page refresh)
'switch_value_undo' => false, // set checkbox to the original value (user will lose the value that was recently input)
],
'on_success' => [
'status_color' => '#42ba96', // set a custom text color instead of the green
'status_color_duration' => 3000, // how long (in milliseconds) should the text stay that color (0 for infinite, aka until page refresh)
],
'auto_update_row' => true, // update related columns in same row, after the AJAX call?
]);
// editable_switch
CRUD::addColumn([
'name' => 'agreed',
'label' => 'Agreed',
'type' => 'editable_switch',
// Optionals
// All the options available on editable_checkbox are available here too, plus;
'color' => 'success',
'onLabel' => '✓',
'offLabel' => '✕',
]);
// editable_select
CRUD::addColumn([
'name' => 'categories',
'label' => 'Categories',
'type' => 'editable_select',
'options' => \App\Models\Category::all()->pluck('name', 'id')->toArray(),
// or
'options' => (function ($entry) {
return \App\Models\Category::whereDate('created_at', '<=', $entry->created_at)
->pluck('name', 'id')->toArray(),
}),
// or
'options' => [
'1' => 'One',
'2' => 'Two',
'3' => 'Three',
],
// Optionals
'underlined' => true, // show a dotted line under the editable column for differentiation? default: true
'save_on_focusout' => true, // if user clicks out, the value should be saved (instead of greyed out)
'save_on_change' => true,
'on_error' => [
'text_color' => '#df4759', // set a custom text color instead of the red
'text_color_duration' => 0, // how long (in milliseconds) should the text stay that color (0 for infinite, aka until page refresh)
'text_value_undo' => false, // set text to the original value (user will lose the value that was recently input)
],
'on_success' => [
'text_color' => '#42ba96', // set a custom text color instead of the green
'text_color_duration' => 3000, // how long (in milliseconds) should the text stay that color (0 for infinite, aka until page refresh)
],
'auto_update_row' => true, // update related columns in same row, after the AJAX call?
]);
}
Step 3.A. Then inside setupMinorUpdateOperation()
, define what FormRequest
you want to use for validation. You can use the exact same FormRequest that you've used in your Create/Update operations, because MinorUpdate
will only consider the validation rule for the currently edited attribute (and ignore everything else). So in most cases you just need to do:
protected function setupMinorUpdateOperation()
{
$this->crud->setValidation(StoreRequest::class);
}
Step 3.B. Alternatively, if you don't want to use a FormRequest for validation, but instead want to write some custom validation logic, or you need to modify the saving process, you can easily do that too. Just override the methods saveMinorUpdateFormValidation()
(to override the validation), and saveMinorUpdateEntry()
(to override the saving process). This methods are used by saveMinorUpdate()
which you may also override although it's not really necessary. The example below shows how to confirm/deny the edit. Modify it so it fits your project, it's in your control.
public function saveMinorUpdateFormValidation()
{
// validation example for the "price"
// note that this is just an example, you may do this with the FormRequest
if (request('attribute') === 'price' && !is_numeric(request('value'))) {
throw ValidationException::withMessages([
'price' => ['The price has to be a number.'],
]);
}
}
public function saveMinorUpdateEntry()
{
// Save the minor update
$entry = $this->crud->getModel()->find(request('id'));
$entry->{request('attribute')} = request('value');
// Perform specific logic
$entry->status = 'draft';
$entry->save();
return $entry->refresh();
}
null
on the select columnIf your column is nullable on database and you want to allow your users to send an empty selection you should add the "empty option" yourself when providing the select options.
CRUD::addColumn([
'name' => 'categories',
'label' => 'Categories',
'type' => 'editable_select',
'options' => array_merge(['' => 'No category'], \App\Models\Category::all()->pluck('name', 'id')->toArray()),
// or
'options' => [
'' => 'No Category',
'1' => 'One',
'2' => 'Two',
'3' => 'Three',
],
]);
Editable columns need to know what search logic to use. We are working on a way to avoid this step, but as of now, you should manually define the searchLogic
that should be applied for each column type. Example:
CRUD::addColumn([
'name' => 'email',
'type' => 'editable_text',
'label' => 'Email',
'searchLogic' => 'text', // this will tell backpack to use the "text" column search logic.
// or alternatively provide your own custom search logic in a closure as you would do for any other column
'searchLogic' => function ($query, $column, $searchTerm) {
$query->orWhere('email', 'like', '%'.$searchTerm.'%');
});
]);
For text based columns you can just tell Backpack to use the text
column searchLogic
as shown in the example above.
At the moment the other columns don't have any default searchLogic
so you should write your own if needed.
| Editable Column | Apply Search Logic From Column | |:-:|:-:| | editable_text | text | | editable_checkbox | write your custom | | editable_switch | write your custom | | editable_select | write your custom |
If you want to reload the table after a column is updated you can use the forceReloadAfterUpdate
setting. This will redraw the whole table on update Eg. CRUD::setOperationSetting('forceReloadAfterUpdate', true)
in your setupListOperation()
Alternatively you can just trigger full table the reload if some specific columns change. For That you can set the forceReloadAfterUpdate
to an array of column names, or a single string of a column name, that should trigger the reload. Eg. CRUD::setOperationSetting('forceReloadAfterUpdate', ['price', 'status'])
or CRUD::setOperationSetting('forceReloadAfterUpdate', 'status')
in your setupListOperation()
.
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
Big thanks to Kevin Ohashi of Review Signal and NameBio.com, who has sponsored building this addon. If you need a Backpack addon too, reach out, we love to build them. Created by:
This project was released under EULA, so you can install it on top of any Backpack & Laravel project. Please see the license file for more information.
You don't currently have access to this package. To gain access, go ahead and purchase it. You'll get: