Unable to implement custom action for GridField

Hi All,

I’m having difficulty getting the ‘GridFieldCustomAction’ working in the example given here.

I’ve copied the exact class “GridFieldCustomAction” to my code base and done this to add in to my exisiting grid.

$grid = new GridField(
            'Furniture',
            'Example Grid',
            $this->Property->Furniture(),
            GridFieldConfig::create()
                ->addComponent(new GridFieldButtonRow('before'))
                ->addComponent(new GridFieldToolbarHeader())
                ->addComponent(new GridFieldTitleHeader())
                ->addComponent(new GridFieldEditableColumns())
                ->addComponent(new GridFieldSortableHeader())
                ->addComponent(new GridFieldCustomAction())
        );

It keeps giving me this error

[Emergency] Uncaught Error: Class ‘GridFieldCustomAction’ not found

Like it cannot find the newly added class for some reason.

I’ve tried even adding it the

use SilverStripe\Forms\GridField\

namespace and importing but it still didn’t work.

It feels like I’m missing a some sort of a configuration to tell silverstripe that I’ve added a new class.

I’m bit stuck on this any help is much appreciated.

** I tried the usual /dev/build and flush all but it didn’t help :frowning:

Also please point me to a working example of adding a new column or a new action to the GridField.
preferably here.

Thank you,
Isuru

It’s most likely a namespacing issue as you suggest. Is the class where your Gridfield exists in a namespace? Is you custom action class in a namespace?

Thank you very much for your reply.

No I did not add it to a name space first. But tried after adding in. No luck yet. Silverstripe documentation definitely needs improving. :-/

This is my custom action class. I’ve changed where I tired to add the new action. This time I tried to add to a default GridField generated by ModelAdmin.

<? 
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
use SilverStripe\Forms\GridField\GridField_ActionProvider;
use SilverStripe\Forms\GridField\GridField_ActionMenuItem;
use SilverStripe\Forms\GridField\GridField_FormAction;
use SilverStripe\Control\Controller;

class GridFieldCustomAction implements GridField_ColumnProvider, GridField_ActionProvider, GridField_ActionMenuItem
{

    public function getTitle($gridField, $record, $columnName)
    {
        return 'Custom action';
    }
    
    public function getCustomAction($gridField, $record)
    {
        if (!$record->canEdit()) {
            return;
        }
        
        return GridField_FormAction::create(
            $gridField,
            'CustomAction'.$record->ID,
            'Custom action',
            "docustomaction",
            ['RecordID' => $record->ID]
         )->addExtraClass(
            'action-menu--handled'
        );
    }
    
    public function getExtraData($gridField, $record, $columnName)
    {
        $field = $this->getCustomAction($gridField, $record);
        
        if (!$field) {
            return;
        }

        return $field->getAttributes();
    }
    
    public function getGroup($gridField, $record, $columnName)
    {
        return GridField_ActionMenuItem::DEFAULT_GROUP;
    }

    public function augmentColumns($gridField, &$columns) 
    {
        if (!in_array('Actions', $columns)) {
            $columns[] = 'Actions';
        }
    }

    public function getColumnAttributes($gridField, $record, $columnName) 
    {
        return ['class' => 'grid-field__col-compact'];
    }

    public function getColumnMetadata($gridField, $columnName) 
    {
        if ($columnName === 'Actions') {
            return ['title' => ''];
        }
    }

    public function getColumnsHandled($gridField) 
    {
        return ['Actions'];
    }

    public function getColumnContent($gridField, $record, $columnName) 
    {
        $field = $this->getCustomAction($gridField, $record);
                
        if (!$field) {
            return;
        }

        return $field->Field();
    }

    public function getActions($gridField) 
    {
        return ['docustomaction'];
    }

    public function handleAction(GridField $gridField, $actionName, $arguments, $data) 
    {
        if ($actionName !== 'docustomaction') {
            return;
        }
        // perform your action here

        // output a success message to the user
        Controller::curr()->getResponse()->setStatusCode(
            200,
            'Do Custom Action Done.'
        );
    }
}

And this is my ModelAdmin class


<?php
use SilverStripe\Admin\ModelAdmin;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Member;
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldExportButton;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Forms\GridField\GridFieldPrintButton;
use SilverStripe\Forms\GridField\GridFieldPaginator;

class InspectionReportsAdmin extends ModelAdmin 
{

    private static $managed_models = [
        'InspectionReports'
    ];

    private static $url_segment = 'inspection-reports';

    private static $menu_title = 'Inspection Reports';

    private static $menu_icon_class = 'font-icon-book-open';

    public function getList() 
    {   
        // Show only Open inspection reports to users except admins.
        $list = parent::getList();
        if(!Permission::checkMember(Member::currentUser(), "ADMIN")) {
            if($this->modelClass == 'InspectionReports') {
                $list = $list->exclude('Status', 'Completed');
            }
        }
        return $list;
    }

    public function getEditForm($id = null, $fields = null)
    {
        
        $form = parent::getEditForm($id, $fields);

        // $gridFieldName is generated from the ModelClass, eg if the Class 'Product'
        // is managed by this ModelAdmin, the GridField for it will also be named 'Product'
        $gridFieldName = $this->sanitiseClassName($this->modelClass);
        $gridField = $form->Fields()->fieldByName($gridFieldName);

        // modify the list view.
        $gridField->getConfig()->addComponent(new GridFieldCustomAction());

        return $form;
    }

}

I will paste the entire error in case it helps.

# Emergency] Uncaught Error: Class 'GridFieldCustomAction' not found

### GET /silverstripe/admin/inspection-reports/

Line  **48**  in  **/Applications/MAMP/htdocs/silverstripe/app/src/InspectionReportsAdmin.php**

### Source

39 public function getEditForm($id = null, $fields = null) 40 { 41 42 $form = parent::getEditForm($id, $fields); 43 44 $gridFieldName = $this->sanitiseClassName($this->modelClass); 45 $gridField = $form->Fields()->fieldByName($gridFieldName); 46 47 // modify the list view. 48 $gridField->getConfig()->addComponent(new GridFieldCustomAction()); 49 50 return $form; 51 } 52 53 }

### Trace

* **InspectionReportsAdmin->getEditForm()**
LeftAndMain.php:1333
* **SilverStripe\Admin\LeftAndMain->EditForm()**

* **call_user_func_array(Array, Array)**
ViewableData.php:485
* **SilverStripe\View\ViewableData->obj(EditForm, , 1)**
ViewableData.php:547
* **SilverStripe\View\ViewableData->XML_val(EditForm, , 1)**
SSViewer_Scope.php:323
* **SilverStripe\View\SSViewer_Scope->__call(XML_val, Array)**
SSViewer_DataPresenter.php:309
* **SilverStripe\View\SSViewer_DataPresenter->__call(XML_val, Array)**
.cachevendor.silverstripe.admin.templates.SilverStripe.Admin.Includes.ModelAdmin_Content.ss:84
* **include(/private/var/folders/dt/f8y7lbg178j6lrd3nxyfkd3m0000gn/T/silverstripe-cache-php7.3.8-Applications-MAMP-htdocs-silverstripe/isurup/.cachevendor.silverstripe.admin.templates.SilverStripe.Admin.Includes.ModelAdmin_Content.ss)**
SSViewer.php:602
* **SilverStripe\View\SSViewer->includeGeneratedTemplate(/var/folders/dt/f8y7lbg178j6lrd3nxyfkd3m0000gn/T/silverstripe-cache-php7.3.8-Applications-MAMP-htdocs-silverstripe/isurup/.cachevendor.silverstripe.admin.templates.SilverStripe.Admin.Includes.ModelAdmin_Content.ss, InspectionReportsAdmin, , Array, )**
SSViewer.php:674
* **SilverStripe\View\SSViewer->process(InspectionReportsAdmin, )**
ViewableData.php:401
* **SilverStripe\View\ViewableData->renderWith(SilverStripe\View\SSViewer)**
LeftAndMain.php:1129
* **SilverStripe\Admin\LeftAndMain->Content()**

* **call_user_func_array(Array, Array)**
ViewableData.php:485
* **SilverStripe\View\ViewableData->obj(Content, , 1)**
ViewableData.php:547
* **SilverStripe\View\ViewableData->XML_val(Content, , 1)**
SSViewer_Scope.php:323
* **SilverStripe\View\SSViewer_Scope->__call(XML_val, Array)**
SSViewer_DataPresenter.php:309
* **SilverStripe\View\SSViewer_DataPresenter->__call(XML_val, Array)**
.cachevendor.silverstripe.admin.templates.SilverStripe.Admin.LeftAndMain.ss:41
* **include(/private/var/folders/dt/f8y7lbg178j6lrd3nxyfkd3m0000gn/T/silverstripe-cache-php7.3.8-Applications-MAMP-htdocs-silverstripe/isurup/.cachevendor.silverstripe.admin.templates.SilverStripe.Admin.LeftAndMain.ss)**
SSViewer.php:602
* **SilverStripe\View\SSViewer->includeGeneratedTemplate(/var/folders/dt/f8y7lbg178j6lrd3nxyfkd3m0000gn/T/silverstripe-cache-php7.3.8-Applications-MAMP-htdocs-silverstripe/isurup/.cachevendor.silverstripe.admin.templates.SilverStripe.Admin.LeftAndMain.ss, InspectionReportsAdmin, , Array, )**
SSViewer.php:674
* **SilverStripe\View\SSViewer->process(InspectionReportsAdmin, )**
ViewableData.php:401
* **SilverStripe\View\ViewableData->renderWith(SilverStripe\View\SSViewer)**
LeftAndMain.php:985
* **SilverStripe\Admin\LeftAndMain->SilverStripe\Admin\{closure}()**

* **call_user_func(Closure)**
PjaxResponseNegotiator.php:92
* **SilverStripe\Control\PjaxResponseNegotiator->respond(SilverStripe\Control\HTTPRequest)**
LeftAndMain.php:828
* **SilverStripe\Admin\LeftAndMain->index(SilverStripe\Control\HTTPRequest)**
RequestHandler.php:323
* **SilverStripe\Control\RequestHandler->handleAction(SilverStripe\Control\HTTPRequest, index)**
Controller.php:284
* **SilverStripe\Control\Controller->handleAction(SilverStripe\Control\HTTPRequest, index)**
RequestHandler.php:202
* **SilverStripe\Control\RequestHandler->handleRequest(SilverStripe\Control\HTTPRequest)**
Controller.php:212
* **SilverStripe\Control\Controller->handleRequest(SilverStripe\Control\HTTPRequest)**
LeftAndMain.php:757
* **SilverStripe\Admin\LeftAndMain->handleRequest(SilverStripe\Control\HTTPRequest)**
AdminRootController.php:123
* **SilverStripe\Admin\AdminRootController->handleRequest(SilverStripe\Control\HTTPRequest)**
Director.php:360
* **SilverStripe\Control\Director->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)**
VersionedHTTPMiddleware.php:41
* **SilverStripe\Versioned\VersionedHTTPMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
ExecMetricMiddleware.php:20
* **SilverStripe\Control\Middleware\ExecMetricMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
ConfirmationMiddleware.php:254
* **SilverStripe\Control\Middleware\ConfirmationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
ConfirmationMiddleware.php:254
* **SilverStripe\Control\Middleware\ConfirmationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
PasswordExpirationMiddleware.php:84
* **SilverStripe\Security\PasswordExpirationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
BasicAuthMiddleware.php:68
* **SilverStripe\Security\BasicAuthMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
AuthenticationMiddleware.php:61
* **SilverStripe\Security\AuthenticationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
CanonicalURLMiddleware.php:190
* **SilverStripe\Control\Middleware\CanonicalURLMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
HTTPCacheControlMiddleware.php:42
* **SilverStripe\Control\Middleware\HTTPCacheControlMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
ChangeDetectionMiddleware.php:28
* **SilverStripe\Control\Middleware\ChangeDetectionMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
FlushMiddleware.php:27
* **SilverStripe\Control\Middleware\FlushMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
RequestProcessor.php:66
* **SilverStripe\Control\RequestProcessor->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
SessionMiddleware.php:20
* **SilverStripe\Control\Middleware\SessionMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
AllowedHostsMiddleware.php:60
* **SilverStripe\Control\Middleware\AllowedHostsMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
TrustedProxyMiddleware.php:176
* **SilverStripe\Control\Middleware\TrustedProxyMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)**
HTTPMiddlewareAware.php:62
* **SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)**
HTTPMiddlewareAware.php:65
* **SilverStripe\Control\Director->callMiddleware(SilverStripe\Control\HTTPRequest, Closure)**
Director.php:369
* **SilverStripe\Control\Director->handleRequest(SilverStripe\Control\HTTPRequest)**
HTTPApplication.php:117
* **SilverStripe\Control\HTTPApplication::SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)**

* **call_user_func(Closure, SilverStripe\Control\HTTPRequest)**
HTTPApplication.php:136
* **SilverStripe\Control\HTTPApplication->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)**
HTTPMiddlewareAware.php:65
* **SilverStripe\Control\HTTPApplication->callMiddleware(SilverStripe\Control\HTTPRequest, Closure)**
HTTPApplication.php:137
* **SilverStripe\Control\HTTPApplication->execute(SilverStripe\Control\HTTPRequest, Closure, )**
HTTPApplication.php:116
* **SilverStripe\Control\HTTPApplication->handle(SilverStripe\Control\HTTPRequest)**
index.php:24

Thank you very much for your help.

Try adding a leading slash on your class name:

$gridField->getConfig()->addComponent(new \GridFieldCustomAction());

Thanks again :pray:. Tried it . But still no luck.

[Emergency] Uncaught Error: Class 'GridFieldCustomAction' not found
GET /silverstripe/admin/inspection-reports/
Line 50 in /Applications/MAMP/htdocs/silverstripe/app/src/InspectionReportsAdmin.php

Source
41         
42         $form = parent::getEditForm($id, $fields);
43 
44         // $gridFieldName is generated from the ModelClass, eg if the Class 'Product'
45         // is managed by this ModelAdmin, the GridField for it will also be named 'Product'
46         $gridFieldName = $this->sanitiseClassName($this->modelClass);
47         $gridField = $form->Fields()->fieldByName($gridFieldName);
48 
49         // modify the list view.
50         $gridField->getConfig()->addComponent(new \GridFieldCustomAction());
51 
52         return $form;
53     }
54 
55 }
Trace
InspectionReportsAdmin->getEditForm()
LeftAndMain.php:1333
SilverStripe\Admin\LeftAndMain->EditForm()
call_user_func_array(Array, Array)
ViewableData.php:485

Have anyone done this or have any tutorials on how to do this? Thanks

You might find the following useful:

or https://github.com/jinjie/duplicate-dataobject.git
which is similar. I was able to create a working custom action from these.