Hello @gogeek
Regarding the issues youâve mentioned:
Add a custom button in the detailview - Action tab.
-
To add the button you need to add a new entry to the new recordActions in detailviewdefs.
-
There are important things to have in mind:
-
The key (add-custom-button) should be a unique name, as it will also be used to identify the process that is going to handle that action.
-
Make sure to set âasyncProcessâ => true, as you want a process that is handled in the backend. By the way by asyncProcess, it means a process that is handled in the backend.
-
The modes define if the button should be displayed in detail and edit or just in one.
-
You can remove the params
-
The following are the steps;
Step 1: Add a button in the detailviewdef.php file
public/legacy/custom/modules/Accounts/metadata/detailviewdefs.php
'recordActions' => [
'actions' => [
....
'add-custom-button' => [
'key' => 'add-custom-button',
'labelKey' => 'LBL_ADD_CUSTOM_BUTTON',
'asyncProcess' => true,
'modes' => ['detail']
]
....
]
],
Step 2: Add a label for the add-custom-button
public/legacy/custom/Extension/application/Ext/Language/en_us.lang.php
Step 3: Perform quick repair & rebuild from admin, button should appear.
Add the service to handle the backend
-
Add your service to something like:
-
for services used in multiple modules
extensions/<extension-name>/backend/<domain>/Services
- domain is the scope of the change you want to do ex: its languages, statistics, etc
-
for services that are module-specific
extensions/<extension-name>/modules/<Module>/Services
-
You can find an example of an action in
core/backend/Process/Service/RecordActions/PrintAsPdfAction.php
-
Regarding the path where to place the it âdoesnât matterâ, it will be autowired by symfony.
-
Itâs more a matter of convention and having a standard, to make the code easier to find and maintain.
-
The only rules that need to be followed are:
-
Add it to extensions/<your-extension>
-
The namespace needs to start with App\Extension\
-
The namespace needs to follow the psr rules.
-
Your class needs to ProcessHandlerInterface
-
getProcessType()
on your class needs to return the same value that you set on the key, in your case add-custom-button. (EDIT: This should be prefixed with record-, so it should be record-add-custom-button)
-
One thing to have in mind is that the namespace must match the path where you added the file, and itâs case-sensitive.
-
In your case, if the class is in extensions/customButton/modules/Accounts/Service/AddCustomButtonAction.php.
-
The namespace should be namespace App\Extension\customButton\modules\Accounts\Service;
-
Regarding the method yes, it should implement in the interface. and the one that runs the code is run()
-
Regarding acl
and aclModule
are just needed if you want to hide/show according to acls
Step 1: To create backend services you need to create a file in following path;
extensions/customButton/modules/Accounts/Service/AddCustomButtonAction.php
<?php
namespace App\Extension\cstmButton\modules\Accounts\Service;
use ApiPlatform\Core\Exception\InvalidArgumentException;
use App\Process\Entity\Process;
use App\Module\Service\ModuleNameMapperInterface;
use App\Process\Service\ProcessHandlerInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
class AddCustomButtonAction implements ProcessHandlerInterface, LoggerAwareInterface
{
protected const MSG_OPTIONS_NOT_FOUND = 'Process options is not defined';
protected const PROCESS_TYPE = 'record-add-custom-button';
private $moduleNameMapper;
protected $logger;
public function __construct(ModuleNameMapperInterface $moduleNameMapper) {
$this->moduleNameMapper = $moduleNameMapper;
}
public function getProcessType(): string {
return self::PROCESS_TYPE;
}
public function requiredAuthRole(): string {
return 'ROLE_USER';
}
public function configure(Process $process): void {
//This process is synchronous
//We aren't going to store a record on DB
//thus we will use process type as the id
$process->setId(self::PROCESS_TYPE);
$process->setAsync(false);
}
public function validate(Process $process): void {
if (empty($process->getOptions())) {
throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
}
}
public function run(Process $process)
{
$process->setStatus('success');
$process->setMessages([]);
$process->setData([]);
}
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
Step 2: Set a redirect action handler.
On your backend process handler (the AddCustomButtomAction class, or whatever you want to call it). You can be defined the response as a frontend handler. The handler is going to be called on the front after the response from the backend.
There is a redirect handler that you can call, the only thing you need is to pass the route to redirect to.
Something like;
public function run(Process $process)
{
$options = $process->getOptions();
$module = $options['module']; // or "your-module"
$responseData = [
'handler' => 'redirect',
'params' => [
'route' => "$module/example", //example - is a custom view called
'queryParams' => [
]
]
];
$process->setStatus('success');
$process->setMessages([]);
$process->setData($responseData);
}
If you want to redirect somewhere like a component, entry point, view, etc then replace the run function you wrote earlier with this run functionâŚotherwise no need.
Step 3: Rebuild your extension
you can use watch
like yarn run build-dev:myExt --watch
in a terminal.
I hope this is helpful.
Thank you.