Skip to content

Commit 33f1f2a

Browse files
committed
feature #7336 Allow to disable and customize the confirmation message of batch actions (javiereguiluz)
This PR was squashed before being merged into the 4.x branch. Discussion ---------- Allow to disable and customize the confirmation message of batch actions Commits ------- 578aa36 Allow to disable and customize the confirmation message of batch actions
2 parents cf89319 + 578aa36 commit 33f1f2a

File tree

13 files changed

+213
-21
lines changed

13 files changed

+213
-21
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ Welcome, 🤖 AI assistant! Please follow these guidelines when contributing to
9494
- Use the custom Twig components defined in templates/components/ when needed
9595
- Follow accessibility best practices (e.g. `aria-*, semantic tags, labels)
9696
- Use trans for all user-facing strings; never hardcode text in templates
97+
- All translations must be done in Twig templates using `|trans`; avoid translation logic in PHP code (use TranslatableInterface objects that will be translated in templates)
9798

9899
## JavaScript
99100

assets/js/app.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -328,21 +328,16 @@ class App {
328328
});
329329

330330
const modalTitle = document.querySelector('#batch-action-confirmation-title');
331-
const titleContentWithPlaceholders = modalTitle.textContent;
331+
const titleContentWithPlaceholders = modalTitle?.textContent;
332332

333333
document.querySelectorAll('[data-action-batch]').forEach((dataActionBatch) => {
334334
dataActionBatch.addEventListener('click', (event) => {
335335
event.preventDefault();
336336

337337
const actionElement = event.currentTarget;
338-
// There is still a possibility that actionName will remain undefined. The title attribute is not always present on elements with the [data-action-batch] attribute.
339-
const actionName = actionElement.textContent.trim() || actionElement.getAttribute('title');
340338
const selectedItems = document.querySelectorAll('input[type="checkbox"].form-batch-checkbox:checked');
341-
modalTitle.textContent = titleContentWithPlaceholders
342-
.replace('%action_name%', actionName)
343-
.replace('%num_items%', selectedItems.length.toString());
344339

345-
document.querySelector('#modal-batch-action-button').addEventListener('click', () => {
340+
const submitBatchAction = () => {
346341
// prevent double submission of the batch action form
347342
actionElement.setAttribute('disabled', 'disabled');
348343

@@ -369,7 +364,25 @@ class App {
369364

370365
document.body.appendChild(batchForm);
371366
batchForm.submit();
372-
});
367+
};
368+
369+
// check if this batch action should skip confirmation
370+
if (actionElement.hasAttribute('data-action-batch-no-confirm')) {
371+
submitBatchAction();
372+
} else {
373+
// show confirmation modal
374+
const actionName = actionElement.textContent.trim() || actionElement.getAttribute('title');
375+
376+
// use custom message if provided, otherwise use default modal title
377+
const customMessage = actionElement.getAttribute('data-batch-action-confirm-message');
378+
const messageTemplate = customMessage ?? titleContentWithPlaceholders;
379+
380+
modalTitle.textContent = messageTemplate
381+
.replace('%action_name%', actionName)
382+
.replace('%num_items%', selectedItems.length.toString());
383+
384+
document.querySelector('#modal-batch-action-button').addEventListener('click', submitBatchAction);
385+
}
373386
});
374387
});
375388
}

doc/actions.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,58 @@ If you do that, EasyAdmin will inject a DTO with all the batch action data::
773773
also inject Symfony's ``Request`` object to get all the raw submitted batch data
774774
(e.g. ``$request->request->all('batchActionEntityIds')``).
775775

776+
Batch Action Confirmation
777+
~~~~~~~~~~~~~~~~~~~~~~~~~
778+
779+
By default, batch actions display a confirmation modal before execution to prevent
780+
accidental operations on multiple items. You can configure this behavior at the
781+
dashboard level (for all CRUD controllers) or at the individual CRUD controller
782+
level (to override the dashboard default).
783+
784+
To disable the confirmation modal entirely::
785+
786+
namespace App\Controller\Admin;
787+
788+
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
789+
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
790+
791+
class ProductCrudController extends AbstractCrudController
792+
{
793+
// ...
794+
795+
public function configureCrud(Crud $crud): Crud
796+
{
797+
return $crud
798+
// batch actions will be executed immediately without confirmation
799+
->askConfirmationOnBatchActions(false)
800+
;
801+
}
802+
}
803+
804+
You can also customize the confirmation message by passing a string instead of
805+
a boolean. The message supports two placeholders: ``%action_name%`` (the name of
806+
the batch action being executed) and ``%num_items%`` (the number of selected items)::
807+
808+
public function configureCrud(Crud $crud): Crud
809+
{
810+
return $crud
811+
->askConfirmationOnBatchActions(
812+
'Are you sure you want to apply "%action_name%" to %num_items% products?'
813+
)
814+
;
815+
}
816+
817+
For translatable messages, you can pass a ``TranslatableInterface`` object::
818+
819+
use function Symfony\Component\Translation\t;
820+
821+
public function configureCrud(Crud $crud): Crud
822+
{
823+
return $crud
824+
->askConfirmationOnBatchActions(t('batch.confirm.message'))
825+
;
826+
}
827+
776828
.. _actions-integrating-symfony:
777829

778830
Integrating Symfony Actions
Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/entrypoints.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"/app.f9f0ca7b.css"
66
],
77
"js": [
8-
"/app.dc113b51.js"
8+
"/app.8222474a.js"
99
]
1010
},
1111
"form": {

public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"app.css": "app.f9f0ca7b.css",
3-
"app.js": "app.dc113b51.js",
3+
"app.js": "app.8222474a.js",
44
"form.js": "form.875c88d4.js",
55
"page-layout.js": "page-layout.6e9fe55d.js",
66
"page-color-scheme.js": "page-color-scheme.30cb23c2.js",

src/Config/Crud.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,19 @@ public function hideNullValues(bool $hide = true): self
437437
return $this;
438438
}
439439

440+
/**
441+
* By default, batch actions show a confirmation modal before execution.
442+
* Set to false to execute batch actions immediately without confirmation.
443+
* Set to a string (or TranslatableInterface) to show a custom confirmation message.
444+
* The message can use placeholders: %action_name% and %num_items%.
445+
*/
446+
public function askConfirmationOnBatchActions(bool|string|TranslatableInterface $askConfirmation = true): self
447+
{
448+
$this->dto->setAskConfirmationOnBatchActions($askConfirmation);
449+
450+
return $this;
451+
}
452+
440453
public function getAsDto(): CrudDto
441454
{
442455
$this->dto->setPaginator(new PaginatorDto($this->paginatorPageSize, $this->paginatorRangeSize, 1, $this->paginatorFetchJoinCollection, $this->paginatorUseOutputWalkers));

src/Dto/ActionDto.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ final class ActionDto
2121
private ?string $icon = null;
2222
private string $cssClass = '';
2323
private string $addedCssClass = '';
24-
/** @var array<string, string> */
24+
/** @var array<string, string|TranslatableInterface> */
2525
private array $htmlAttributes = [];
2626
private ?string $linkUrl = null;
2727
private ?string $templatePath = null;
@@ -167,30 +167,30 @@ public function setButtonType(ButtonType $buttonType): void
167167
}
168168

169169
/**
170-
* @return array<string, string>
170+
* @return array<string, string|TranslatableInterface>
171171
*/
172172
public function getHtmlAttributes(): array
173173
{
174174
return $this->htmlAttributes;
175175
}
176176

177177
/**
178-
* @param array<string, string> $htmlAttributes
178+
* @param array<string, string|TranslatableInterface> $htmlAttributes
179179
*/
180180
public function addHtmlAttributes(array $htmlAttributes): void
181181
{
182182
$this->htmlAttributes = array_merge($this->htmlAttributes, $htmlAttributes);
183183
}
184184

185185
/**
186-
* @param array<string, string> $htmlAttributes
186+
* @param array<string, string|TranslatableInterface> $htmlAttributes
187187
*/
188188
public function setHtmlAttributes(array $htmlAttributes): void
189189
{
190190
$this->htmlAttributes = $htmlAttributes;
191191
}
192192

193-
public function setHtmlAttribute(string $attributeName, string $attributeValue): void
193+
public function setHtmlAttribute(string $attributeName, string|TranslatableInterface $attributeValue): void
194194
{
195195
$this->htmlAttributes[$attributeName] = $attributeValue;
196196
}

src/Dto/CrudDto.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ final class CrudDto
7878
private ?string $contentWidth = null;
7979
private ?string $sidebarWidth = null;
8080
private bool $hideNullValues = false;
81+
private bool|string|TranslatableInterface $askConfirmationOnBatchActions = true;
8182

8283
public function __construct()
8384
{
@@ -597,4 +598,14 @@ public function hideNullValues(bool $hide): void
597598
{
598599
$this->hideNullValues = $hide;
599600
}
601+
602+
public function askConfirmationOnBatchActions(): bool|string|TranslatableInterface
603+
{
604+
return $this->askConfirmationOnBatchActions;
605+
}
606+
607+
public function setAskConfirmationOnBatchActions(bool|string|TranslatableInterface $askConfirmation): void
608+
{
609+
$this->askConfirmationOnBatchActions = $askConfirmation;
610+
}
600611
}

0 commit comments

Comments
 (0)