1

My goal is it to add a custom FormAction to a DataObjects EditForm inside a ModelAdmin, next to the "Save" and "Delete" action.

The setup:

With updateCMSActions I can add that button.

class MyActionEventExtension extends DataExtension {
    public function updateCMSActions(FieldList $actions) {

        if($this->owner->canEdit(Member::currentUser())) {
          $actions->push(FormAction::create('doMyAction', 'Action'));
        }
        return $actions;
    }
}

This works perfectly fine.

Following this answer on stackoverflow I created a LeftAndMainExtension for the actions handler.

class MyActionLeftAndMainExtension extends LeftAndMainExtension {
    private static $allowed_actions = array(
        'doMyAction'
    );

    public function doMyAction($data, $form) {
        // Do stuff.
        // ... I never get here.


        // Return stuff
        $this->owner->response->addHeader(
            'X-Status',
            rawurlencode('Success message!') 
        );

        return $this->owner->getResponseNegotiator()
               ->respond($this->owner->request);
    }
}

The corresponding config.yml file looks like this:

LeftAndMain:
  extensions:
    - MyActionLeftAndMainExtension
TheDataObject:
  extensions:
    - MyActionEventExtension

The Problem:

When I click the button, the response gives me "404 Not Found".

The requested URL always is the same:

http://localhost/admin/model-admin-url-slug/TheDataObject/EditForm/field/TheDataObject/item/878/ItemEditForm

Some other solutions I found, suggested to extend the ModelAdmins GridField. This sadly is not an option, since the DataObject I need that action for has alot of relations, which means, it's EditForm also appears in other DataObjects EditForms (nested).

I'm really running out of ideas. Did I miss something within my ModelAdmin? The one I created only implements the basic static vars, so I didn't posted it here.

Any help would be great!

Update:

I ended up, providing a getEditForm method on my ModelAdmin.

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

    $listField = $form->Fields()->fieldByName($this->modelClass);
    if ($gridField = $listField->getConfig()->getComponentByType('GridFieldDetailForm')) {
        $gridField->setItemRequestClass('MyAdminForm_ItemRequest');
    }

    return $form;
}

and extending the GridFieldDetailForm_ItemRequest:

class MyAdminForm_ItemRequest extends GridFieldDetailForm_ItemRequest {
    private static $allowed_actions = array (
        'edit',
        'view',
        'ItemEditForm'
    );

    public function ItemEditForm() {
        $form = parent::ItemEditForm();
        $formActions = $form->Actions();

        // Adds all FormActions provided by the model's `getCMSActions` callback
        if ($actions = $this->record->getCMSActions()) {
            foreach ($actions as $action) {
                $formActions->push($action);
            }
        }

        return $form;
    }

    public function doAction($data, $form) {
        // do stuff here
    }
}

Sadly this doesn't add an action on has_many or many_many relation gridfields.. and because of that, I'll leave the question opened and unanswered. Maybe sometime there will be a better solution.. :)

Community
  • 1
  • 1
jukempff
  • 965
  • 6
  • 12

1 Answers1

0

One very simple answer to this question (if it's an option for you) is to use the Better Buttons module: https://github.com/unclecheese/silverstripe-gridfield-betterbuttons#creating-a-custom-action

It lets you define the actions on the model, which is a bit questionable from an architecture standpoint, but also works pretty well in the context of Silverstripe and ModelAdmin.

Mark Guinn
  • 619
  • 3
  • 8
  • Thank you, I am now running with an Action, provided only at one specific ModelAdmin. As a workaround, this is okay.. But I will checkout gridfield-betterbuttons asap, and come back here, if it's a solution to me! – jukempff Aug 10 '15 at 15:37