Home
NexoPOS

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.