Skip to content

Instantly share code, notes, and snippets.

Created September 13, 2012 03:08
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
GridField Detail form with relation ID populated
class GridFieldConfig_HasManyRelationEditor extends GridFieldConfig {
* @param int $itemsPerPage - How many items per page should show up
public function __construct($itemsPerPage=null) {
$this->addComponent(new GridFieldButtonRow('before'));
$this->addComponent(new GridFieldAddNewButton('buttons-before-left'));
$this->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-left'));
$this->addComponent(new GridFieldToolbarHeader());
$this->addComponent($sort = new GridFieldSortableHeader());
$this->addComponent($filter = new GridFieldFilterHeader());
$this->addComponent(new GridFieldDataColumns());
$this->addComponent(new GridFieldEditButton());
$this->addComponent(new GridFieldDeleteAction());
$this->addComponent($pagination = new GridFieldPaginator($itemsPerPage));
$detailForm = new GridFieldDetailForm();
class GridFieldDetailForm_HasManyItemRequest extends GridFieldDetailForm_ItemRequest {
* Builds an item edit form. The arguments to getCMSFields() are the popupController and
* popupFormName, however this is an experimental API and may change.
* @todo In the future, we will probably need to come up with a tigher object representing a partially
* complete controller with gaps for extra functionality. This, for example, would be a better way
* of letting Security/login put its log-in form inside a UI specified elsewhere.
* @return Form
function ItemEditForm() {
if (empty($this->record)) {
$controller = Controller::curr();
$noActionURL = $controller->removeAction($_REQUEST['url']);
$controller->getResponse()->removeHeader('Location'); //clear the existing redirect
return $controller->redirect($noActionURL, 302);
$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'))
}else{ // adding new record
//Change the Save label to 'Create'
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Create', 'Create'))
->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'add'));
// Add a Cancel link which is a button-like link and link back to one level up.
$curmbs = $this->Breadcrumbs();
if($curmbs && $curmbs->count()>=2){
$one_level_up = $curmbs->offsetGet($curmbs->count()-2);
$text = "
<a class=\"crumb ss-ui-button ss-ui-action-destructive cms-panel-link ui-corner-all\" href=\"".$one_level_up->Link."\">
$actions->push(new LiteralField('cancelbutton', $text));
$fk = $this->gridField->getList()->foreignKey;
$this->record->$fk = $this->gridField->getList()->foreignID;
$form = new Form(
// TODO Coupling with CMS
$toplevelController = $this->getToplevelController();
if($toplevelController && $toplevelController instanceof LeftAndMain) {
// Always show with base template (full width, no other panels),
// regardless of overloaded CMS controller templates.
// TODO Allow customization, e.g. to display an edit form alongside a search form from the CMS controller
$form->addExtraClass('cms-content cms-edit-form center ss-tabset');
$form->setAttribute('data-pjax-fragment', 'CurrentForm Content');
if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
if($toplevelController->hasMethod('Backlink')) {
$form->Backlink = $toplevelController->Backlink();
} elseif($this->popupController->hasMethod('Breadcrumbs')) {
$parents = $this->popupController->Breadcrumbs(false)->items;
$form->Backlink = array_pop($parents)->Link;
} else {
$form->Backlink = $toplevelController->Link();
$cb = $this->component->getItemEditFormCallback();
if($cb) $cb($form, $this);
return $form;
Copy link

Only difference with GridFieldDetailForm_ItemRequest ( is that foreign key is set on record lines 45 and 46, record is always loaded into the form line 55.

This has added benefit that foreign key is available in getCMSFields() and record $defaults are set to the form first time.

Copy link

frank, do you know if this will appear in some silverstripe patch soon?

Copy link

I don't believe it will become part of core..

Copy link


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment