Catch Crud Action With Javascript
When extending a CRUD with custom actions, the logic doesn’t always belong on the backend—sometimes it’s better handled on the frontend, especially for UI interactions.
For example, imagine adding a “Transfer Stock” action to move specific units of a product to a warehouse. Instead of processing this directly, you can trigger a pop-up when the action is clicked, allowing you to load and display a custom Vue component for handling the transfer.
Inject Footer On A Crud Instance
Now, we need to conditionally inject a custom footer on a Crud instance that we want to extend. This means when only a ProductCrud instance is being used, for example. For that, we first need to register a filter.
<?php
namespace Modules\MyModuleNamespace\Providers;
use Illuminate\Support\ServiceProvider;
use App\Classes\Hook;
use App\Classes\Output;
class MyModuleProvider extends ServiceProvider
{
public function register()
{
Hook::addFilter( 'ns-crud-footer', function( Output $output, $namespace ) {
if ( $namespace === 'ns-products' ) {
$output->addView( 'MyModuleNamespace::footer' );
}
return $output;
});
}
}
Here, we've injected a view on the footer of the crud instance that will process "products".
Note that the "ns-products" here refers to an identifier (formerly namespace) of the CRUD component ProductCrud (available on App\Crud\ProductCrud). This means that to inject a Vue into a specific CRUD component, we need to have the identifier first.
Register A Custom Row Action
Now, we need to register a custom row action with the identifier "my-product-transfer".
<?php
namespace Modules\MyModuleNamespace\Providers;
use Illuminate\Support\ServiceProvider;
use App\Classes\Hook;
use App\Services\CrudEntry;
class MyModuleProvider extends ServiceProvider
{
public function register()
{
$namespace = 'ns.products';
Hook::addAction( Product::method( 'setActions' ), function( CrudEntry $row ) {
$row->action(
label: __( 'Transfer Product' ),
identifier: 'my-product-transfer'
);
return $row;
});
}
}
Catching The Action From Javascript
Now we need to catch that action as we haven't defined any specific known type.
<script>
nsEvent.subject().subscribe( event => {
if ( event.identifier === 'ns-table-row-action' && event.value.action.identifier === 'my-product-transfer' ) {
// Display you action here. "event.value.row" contains the actual clicked row.
}
});
</script>
First, we check if the event is "ns-table-row-action", then we check if the action namespace is "my-product-transfer". Then we can execute our component. We'll then need to use a "Popup" object to create a pop-up for our specific component. We'll assume you have correctly registered your Vue component and would like to open it when an action is clicked. We'll use the previous example here.
<script>
nsEvent.subject().subscribe( event => {
if ( event.identifier === 'ns-table-row-action' && event.value.action.identifier === 'my-product-transfer' ) {
const row = event.value.row;
Popup.show( MyModulePopup, { row });
}
});
</script>
From now on, we should be able to see a popup showing up.