Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions 7.x-dev/base-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ This component helps you show a form _anywhere you want_, so the admin can easil
- `operation='create'` - by default, the datatable component will pick up everything that controller sets up for the Create operation; if you want to change the operation it will initialize, you can pass this parameter;
- `:entry="\App\Models\Invoice::find(1)"` - if you want to use UpdateOperation or a custom form operation that needs the entry;
- `:setup="function($crud, $parent) {}"` - if you want to make changes to the operation setup (eg. add/remove fields, configure functionality), you can use this parameter; the closure passed here will be run _after_ the setup of that operation had already completed;
- `:save-actions="[]"` - provide an array of save action definitions or save action classes to replace the defaults (see [Custom save actions](#dataform-custom-save-actions));
- `:form-inside-card="true"` - render the form inside a Backpack card wrapper so it visually matches the default create/update screens; leave it `false` to output only the raw form markup.

**Advanced example:**

Expand All @@ -115,6 +117,33 @@ This component helps you show a form _anywhere you want_, so the admin can easil
/>
```

<a name="dataform-custom-save-actions"></a>
#### Custom save actions

The Dataform component can swap out the default `Save and back / edit / new` buttons with your own logic. Pass an array to the `:save-actions` attribute containing save action classes (or definitions) that implement Backpack's `SaveActionInterface`:

```php
@php
use App\Backpack\Crud\SaveActions\SaveAndApprove;
use Backpack\CRUD\app\Library\CrudPanel\SaveActions\SaveAndBack;
@endphp

<x-bp-dataform
controller="\App\Http\Controllers\Admin\InvoiceCrudController"
:save-actions="[
new SaveAndApprove,
SaveAndBack::class,
]"
/>
```

Each entry in the array can be:
- an instance of a class that implements `SaveActionInterface` (recommended);
- the fully qualified class name of a save action (the container will resolve it);
- a plain array definition (see [`crud-save-actions.md`](crud-save-actions.md)).

Backpack will replace the default actions for that form, honour the order defined by each class, and fallback to the first action if no default applies.

<hr>

<a name="dataform-modal"></a>
Expand All @@ -140,6 +169,7 @@ use \Backpack\DataformModal\Http\Controllers\Operations\CreateInModalOperation;
- `operation='createInModal'` - by default, the component will pick up everything that controller sets up for the Create operation; if you want to change the operation it will initialize, you can pass this parameter, eg: `updateInModal`
- `:entry="\App\Models\Invoice::find(1)"` - if you want to use UpdateInModalOperation or a custom form operation that needs the entry;
- `:setup="function($crud, $parent) {}"` - if you want to make changes to the operation setup (eg. add/remove fields, configure functionality), you can use this parameter; the closure passed here will be run _after_ the setup of that operation had already completed;
- `:save-actions="[]"` - replace the default modal buttons with your own save action classes.

**Advanced example:**

Expand Down Expand Up @@ -172,6 +202,7 @@ Useful if you want to show the entries in the database, for an Eloquent model. T
**Configuration options:**
- `name='invoices_datatable'` - by default, a name will be generated; but you can pick one you can recognize;
- `operation='list'` - by default, the datatable component will pick up everything that controller sets up for the List operation; if you want to change the operation it will initialize, you can pass this parameter;
- `:useFixedHeader="false"` - set this to explicitly enable or disable the sticky header; it defaults to the operation's `useFixedHeader` setting, falling back to `true`;
- `:setup="function($crud, $parent) {}"` - if you want to make changes to the operation setup (eg. add/remove columns, configure functionality), you can use this parameter; the closure passed here will be run _after_ the setup of that operation had already completed;

**Advanced example:**
Expand Down
85 changes: 85 additions & 0 deletions 7.x-dev/crud-save-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,91 @@ There are four save actions registered by Backpack by default. They are:
- ```save_and_new``` (Save and go to create new entity page)
- ```save_and_preview``` (Save and go to show the current entity)

<a name="save-action-classes"></a>
## Save Action Classes

Save actions are now first-class citizens. Instead of maintaining large array definitions in each CrudController, you can encapsulate the behaviour inside PHP classes that implement `Backpack\CRUD\app\Library\CrudPanel\SaveActions\SaveActionInterface`. Backpack ships with `SaveAndBack`, `SaveAndEdit`, `SaveAndNew`, and `SaveAndPreview` as examples, and also provides `SaveAndList` for projects that want an explicit "Save and go to list" button.

### Quick start

1. **Create a class** inside your application (for example `app/Backpack/Crud/SaveActions/SaveAndApprove.php`).
2. **Extend** `AbstractSaveAction` (recommended) or implement `SaveActionInterface` directly.
3. **Override** the methods that describe your button.
4. **Register** the class with `CRUD::addSaveAction()` / `CRUD::replaceSaveActions()` or pass it to Blade components like `<x-bp-dataform>`.

```php
<?php

namespace App\Backpack\Crud\SaveActions;

use Backpack\CRUD\app\Library\CrudPanel\CrudPanel;
use Backpack\CRUD\app\Library\CrudPanel\SaveActions\AbstractSaveAction;
use Illuminate\Http\Request;

class SaveAndApprove extends AbstractSaveAction
{
protected ?int $order = 2;

public function getName(): string
{
return 'save_and_approve';
}

public function getButtonText(): string
{
return trans('backpack::crud.save_action_save_and_approve');
}

public function isVisible(CrudPanel $crud): bool
{
return $crud->hasAccess('update') && $crud->entry?->canBeApproved();
}

public function getRedirectUrl(CrudPanel $crud, Request $request, $itemId = null): ?string
{
return route('admin.invoices.approve', $itemId ?? $request->input('id'));
}
}
```

> **Tip:** `AbstractSaveAction` already implements `toArray()`, order handling, and sensible defaults. Override only what you need. If you must store additional data, you can still return a custom array by implementing `SaveActionInterface` yourself.

### Registering class-based actions

Inside your CrudController you can now pass the class instead of an array:

```php
use App\Backpack\Crud\SaveActions\SaveAndApprove;

CRUD::replaceSaveActions([
new SaveAndApprove(),
\Backpack\CRUD\app\Library\CrudPanel\SaveActions\SaveAndBack::class,
]);
```

Backpack recognizes three inputs when registering save actions:
- an instantiated save action class;
- the fully qualified class name (it is resolved via the container so dependencies can be injected);
- the legacy associative array definition (still supported).

The action `order` is taken from the class (or array) and Backpack reorders conflicts automatically. If you need to adjust the order later you can still call `CRUD::orderSaveActions()`.

### Using classes in Blade components

The `bp-dataform` component accept save action classes through the `:save-actions` attribute. This allows you to reuse the same custom buttons outside CrudControllers:

```php
<x-bp-dataform
controller="\App\Http\Controllers\Admin\InvoiceCrudController"
:save-actions="[
new App\\Backpack\\Crud\\SaveActions\\SaveAndApprove(),
Backpack\\CRUD\\app\\Library\\CrudPanel\\SaveActions\\SaveAndBack::class,
]"
/>
```

When no save actions are provided, Backpack falls back to the defaults registered on the controller.

<a name="save-actions-api"></a>
## Save Actions API

Expand Down