Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add ability to add custom actions to GridField record #526

Closed
wants to merge 7 commits into from

7 participants

Morven Lewis-Everley Sam Minnée Don't Add Me To Your Organization a.k.a The Travis Bot Ingo Schommer Florian Thoma Tim vikas srivastava
Morven Lewis-Everley

Mainly I see this as useful for ModelAdmin, but could be useful elsewhere as well.

Currently GridField only adds Create/Cancel or Save/Delete buttons when editing an object. The record controller now checks if the Model class provides a getCMSActions() method, and if so, uses that.

Also added some extra methods for Publishing and UnPublishing content.

Still rudimentary, but think it would be quite a useful feature.

Morven added some commits
Morven Add check for getCMSActions() on record. If exists (and object in DB)…
… use that instead of default actions.

Add doPublish() method as well, to provide support for Versioned extension on DataObjects
002049a
Morven Add basic unpublish support c43b854
Morven Add form and data parameters to unpublish method aa7c663
Sam Minnée
Owner

There is too much use-case specific stuff and magic in this approach.

  • Don't rely on getCMSActions(), provide configuration options (constructor arguments or setters) in the Detail form object to specify buttons. It then might appropriate in ModelAdmin rather than GridField to interrogate the values in getCMSActions() and pass the resulting buttons to GridFieldDetailForm. Alternatively, GridFieldDetailForm could be designed so that it can be passed a callback to fetch actions, and this callback could be set to:

    $detailFormComponent->setActions(function($record) {
        return $record->getCMSActions();
    });
    
  • Don't hard-code the publish and unpublish action handlers into GridFieldDetailForm. There are a few ways you could do this:

    • Provide a configuration option that let you add more action handlers (perhaps as anonymous functions).
    • Provide an additional GridField component that provided the additional actions.
    • Create a subclass of GridFieldDetailForm specifically for versioned objects.

Once again, the ModelAdmin could be configured to interrogate the managed object to identify which actions were necessary.

mlewis-everley and others added some commits
Morven Lewis-Everley mlewis-everley Merge upstream changes from 3.0.0-rc1 9c9898d
morven Merge commit '3.0.0' into MLE-3.0.0-ModelAdmin 7056681
morven Update gridfield to use Getters and Setters for form actions
Remove publish and unpublish methods, as these can be added via an extension or subclass
Add getters and setters that can be manipulated after creating a new GridFieldDetailFrom()
646fb99
Morven Lewis-Everley

Ok, I have done a lot of reverse engineering of GridField. Hopefully I am getting closer to your comments.

I have removed the Publish and UnPublish methods, and successfully SubClassed GridFieldDetailForm_ItemRequest, adding these methods to that.

I have also removed the getCMSActions check and instead added a getFormActions() and setFormActions() method to GridFieldDetailForm that is passed to GridFieldDetailForm_ItemRequest.

I haven't done anything with ModelAdmin however, so far I have managed to make use of these methods and subclasses in my ModelAdmin subclass (which is currently not ideal, as I have to copy the getEditForm() method from ModelAdmin intio my subclass.

Not sure if ModelAdmin should have some sort of setter to allow overwriting of these actions more easily?

Mo

Morven Lewis-Everley

As far as I can tell, the cleanest way of using the setFormActions() method is to overwrite getEditForm() in your ModelAdmin subclass and add both the new actions and a new ItemRequest subclass (with methods called by your new actions).

So something like this:

function getEditForm($id = null, $fields = null) {
    $form = parent::getEditForm($id = null, $fields = null);    
    $listfield = $form->Fields()->fieldByName([MODELCLASS]);

    $listfield->getConfig()->getComponentByType('GridFieldDetailForm')
        ->setItemRequestClass('[CLASSNAME]_ItemRequest')
        ->setFormActions(singleton($this->modelClass)->getCMSActions());

    return $form;
}
Morven Lewis-Everley mlewis-everley reopened this
Sam Minnée sminnee closed this
Sam Minnée sminnee reopened this
Don't Add Me To Your Organization a.k.a The Travis Bot

This pull request passes (merged 4ac4b23 into 64357a4).

Morven Lewis-Everley

I am going to close this, as I have found that you can edit the Item Form actions in ModelAdmin quite easily by:

  1. Extending GridFieldDetailFrom_ItemRequest.
  2. Adding an ItemEditForm() method to your extension.
  3. Within ItemEditForm() call parent::ItemEditForm()->actions()
  4. Edit actions via the FieldList API.

Not really sure these changes need to be merged into core, so as I said am closing this request.

Ingo Schommer
Owner

Thanks anyway, Morven :)

Florian Thoma

Sorry I didn't quite get it. What is the final general solution to this?
Thanks, xini

Tim

extend GridFieldDetailForm & GridFieldDetailForm_ItemRequest
eg.

class VersionedGridFieldDetailForm extends GridFieldDetailForm {    
}

class VersionedGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest {
}

then in VersionedGridFieldDetailForm_ItemRequest

function ItemEditForm() {
        $form = parent::ItemEditForm();
        $actions = $this->record->getCMSActions();

        $form->setActions($actions);
        return $form;
}

or in my case

function ItemEditForm() {
        $form = parent::ItemEditForm();
        $actions = FieldList::create(...actions...);

        $form->setActions($actions);
        return $form;
}

Hope this helps.

Cheers

Florian Thoma

I got it working. Thanks!

vikas srivastava

I am having a problem with this method. My action buttons are only appearing in Model Admin but not in Relation Editor, So when I am editing my dataobject from Model Admin they are working fine, but I have a relation of this dataobject with HomePage and when I try to edit this from HomePage, buttons are not appearing.

http://www.sspaste.com/paste/show/518e3dc335c85 . (See first comment for relation between my DataObject and HomePage).

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 13, 2012
  1. Add check for getCMSActions() on record. If exists (and object in DB)…

    Morven authored
    … use that instead of default actions.
    
    Add doPublish() method as well, to provide support for Versioned extension on DataObjects
  2. Add basic unpublish support

    Morven authored
Commits on Jun 23, 2012
  1. Morven Lewis-Everley
Commits on Jul 2, 2012
  1. Update gridfield to use Getters and Setters for form actions

    morven authored
    Remove publish and unpublish methods, as these can be added via an extension or subclass
    Add getters and setters that can be manipulated after creating a new GridFieldDetailFrom()
Commits on Jul 5, 2012
  1. Morven Lewis-Everley
This page is out of date. Refresh to see the latest.
Showing with 62 additions and 5 deletions.
  1. +62 −5 forms/gridfield/GridFieldDetailForm.php
67 forms/gridfield/GridFieldDetailForm.php
View
@@ -27,6 +27,11 @@ class GridFieldDetailForm implements GridField_URLHandler {
* @var Validator The form validator used for both add and edit fields.
*/
protected $validator;
+
+ /**
+ * @var FieldList
+ */
+ protected $formActions;
/**
* @var String
@@ -57,6 +62,7 @@ function getURLHandlers($gridField) {
*/
public function __construct($name = 'DetailForm') {
$this->name = $name;
+ $this->formActions = new FieldList();
}
/**
@@ -78,10 +84,29 @@ public function handleItem($gridField, $request) {
$handler = Object::create($class, $gridField, $this, $record, $controller, $this->name);
$handler->setTemplate($this->template);
+ $handler->setFormActions($this->getFormActions());
return $handler->handleRequest($request, DataModel::inst());
}
+ /**
+ * Set the actions to be used in ItemEditForm
+ *
+ * @param FieldList $actions
+ * @return FieldList
+ */
+ function setFormActions(FieldList $actions) {
+ $this->formActions = $actions;
+ return $this;
+ }
+
+ /**
+ * @return FieldList
+ */
+ function getFormActions() {
+ return $this->formActions;
+ }
+
/**
* @param String
*/
@@ -138,7 +163,7 @@ public function setItemRequestClass($class) {
/**
* @return String
*/
- public function getItemRequestClass() {
+ public function getItemRequestClass() {
if($this->itemRequestClass) {
return $this->itemRequestClass;
} else if(ClassInfo::exists(get_class($this) . "_ItemRequest")) {
@@ -200,6 +225,12 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
*/
protected $template = 'GridFieldItemEditView';
+ /**
+ *
+ * @var FieldList
+ */
+ protected $formActions;
+
static $url_handlers = array(
'$Action!' => '$Action',
'' => 'edit',
@@ -289,10 +320,18 @@ function ItemEditForm() {
$actions = new FieldList();
if($this->record->ID !== 0) {
- $actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))
- ->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'));
- $actions->push(FormAction::create('doDelete', _t('GridFieldDetailForm.Delete', 'Delete'))
- ->addExtraClass('ss-ui-action-destructive'));
+ // Add check to see if record is providing its own actions.
+ // If not, fall back to default.
+ // Currently custom methods for manipulating data need to be
+ // added to this class via Object::add_extension();
+ if(!$this->getFormActions()->exists()) {
+ $actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))
+ ->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'));
+ $actions->push(FormAction::create('doDelete', _t('GridFieldDetailForm.Delete', 'Delete'))
+ ->addExtraClass('ss-ui-action-destructive'));
+ } else {
+ $actions->merge($this->getFormActions());
+ }
}else{ // adding new record
//Change the Save label to 'Create'
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Create', 'Create'))
@@ -409,6 +448,24 @@ function doDelete($data, $form) {
return $controller->redirect($noActionURL, 302); //redirect back to admin section
}
+
+ /**
+ * Set the actions to be used in ItemEditForm
+ *
+ * @param FieldList $actions
+ * @return FieldList
+ */
+ function setFormActions(FieldList $actions) {
+ $this->formActions = $actions;
+ return $this;
+ }
+
+ /**
+ * @return FieldList
+ */
+ function getFormActions() {
+ return $this->formActions;
+ }
/**
* @param String
Something went wrong with that request. Please try again.