2014-10-19 10:32:34 +02:00
title: GridField
summary: How to use the GridField class for managing tabular data.
# GridField
2017-07-03 03:22:12 +02:00
[GridField ](api:SilverStripe\Forms\GridField\GridField ) is SilverStripe's implementation of data grids. The main purpose of the `FormField` is to display
2014-10-19 10:32:34 +02:00
tabular data in a format that is easy to view and modify. It can be thought of as a HTML table with some tricks.
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridField;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
$field = new GridField($name, $title, $list);
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
< div class = "hint" markdown = '1' >
GridField can only be used with `$list` data sets that are of the type `SS_List` such as `DataList` or `ArrayList` .
< / div >
< div class = "notice" markdown = "1" >
2017-07-03 03:22:12 +02:00
[GridField ](api:SilverStripe\Forms\GridField\GridField ) powers the automated data UI of [ModelAdmin ](api:SilverStripe\Admin\ModelAdmin ). For more information about `ModelAdmin` see the
2016-01-14 11:59:53 +01:00
[Customizing the CMS ](/developer_guides/customising_the_admin_interface ) guide.
2014-10-19 10:32:34 +02:00
< / div >
2017-07-03 03:22:12 +02:00
Each `GridField` is built from a number of components grouped into the [GridFieldConfig ](api:SilverStripe\Forms\GridField\GridFieldConfig ). Without any components,
a `GridField` has almost no functionality. The `GridFieldConfig` instance and the attached [GridFieldComponent ](api:SilverStripe\Forms\GridField\GridFieldComponent ) are
2014-10-19 10:32:34 +02:00
responsible for all the user interactions including formatting data to be readable, modifying data and performing any
actions such as deleting records.
2018-06-25 00:39:53 +02:00
**app/code/Page.php**
2014-10-19 10:32:34 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\CMS\Model\SiteTree;
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
class Page extends SiteTree
{
public function getCMSFields()
2017-08-07 05:11:17 +02:00
{
2017-10-27 04:38:27 +02:00
$fields = parent::getCMSFields();
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
$fields->addFieldToTab('Root.Pages',
new GridField('Pages', 'All pages', SiteTree::get())
);
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
return $fields;
2017-08-07 05:11:17 +02:00
}
2017-10-27 04:38:27 +02:00
}
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
This will display a bare bones `GridField` instance under `Pages` tab in the CMS. As we have not specified the
2017-07-03 03:22:12 +02:00
`GridField` configuration, the default configuration is an instance of [GridFieldConfig_Base ](api:SilverStripe\Forms\GridField\GridFieldConfig_Base ) which provides:
2014-10-19 10:32:34 +02:00
2017-07-03 03:22:12 +02:00
* [GridFieldToolbarHeader ](api:SilverStripe\Forms\GridField\GridFieldToolbarHeader )
* [GridFieldSortableHeader ](api:SilverStripe\Forms\GridField\GridFieldSortableHeader )
* [GridFieldFilterHeader ](api:SilverStripe\Forms\GridField\GridFieldFilterHeader )
* [GridFieldDataColumns ](api:SilverStripe\Forms\GridField\GridFieldDataColumns )
* [GridFieldPageCount ](api:SilverStripe\Forms\GridField\GridFieldPageCount )
* [GridFieldPaginator ](api:SilverStripe\Forms\GridField\GridFieldPaginator )
2014-10-19 10:32:34 +02:00
The configuration of those `GridFieldComponent` instances and the addition or subtraction of components is done through
the `getConfig()` method on `GridField` .
2018-06-25 00:39:53 +02:00
**app/code/Page.php**
2014-10-19 10:32:34 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\CMS\Model\SiteTree;
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
class Page extends SiteTree
{
public function getCMSFields()
2017-08-07 05:11:17 +02:00
{
2017-10-27 04:38:27 +02:00
$fields = parent::getCMSFields();
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
$fields->addFieldToTab('Root.Pages',
$grid = new GridField('Pages', 'All pages', SiteTree::get())
);
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
// GridField configuration
$config = $grid->getConfig();
//
// Modification of existing components can be done by fetching that component.
// Consult the API documentation for each component to determine the configuration
// you can do.
//
2017-11-17 02:04:32 +01:00
$dataColumns = $config->getComponentByType(GridFieldDataColumns::class);
2017-10-27 04:38:27 +02:00
$dataColumns->setDisplayFields([
'Title' => 'Title',
'Link'=> 'URL',
'LastEdited' => 'Changed'
]);
return $fields;
2017-08-07 05:11:17 +02:00
}
2017-10-27 04:38:27 +02:00
}
2017-08-03 05:35:09 +02:00
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
2017-08-03 02:51:32 +02:00
With the `GridFieldConfig` instance, we can modify the behavior of the `GridField` .
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
// `GridFieldConfig::create()` will create an empty configuration (no components).
$config = GridFieldConfig::create();
2014-10-19 10:32:34 +02:00
2017-10-27 04:38:27 +02:00
// add a component
$config->addComponent(new GridFieldDataColumns());
2014-10-19 10:32:34 +02:00
2017-10-27 04:38:27 +02:00
// Update the GridField with our custom configuration
$gridField->setConfig($config);
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
`GridFieldConfig` provides a number of methods to make setting the configuration easier. We can insert a component
before another component by passing the second parameter.
2017-10-26 02:22:02 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
$config->addComponent(new GridFieldFilterHeader(), GridFieldDataColumns::class);
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
We can add multiple components in one call.
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
$config->addComponents(
new GridFieldDataColumns(),
new GridFieldToolbarHeader()
);
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
Or, remove a component.
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
$config->removeComponentsByType(GridFieldDeleteAction::class);
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
Fetch a component to modify it later on.
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
$component = $config->getComponentByType(GridFieldFilterHeader::class)
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
Here is a list of components for use bundled with the core framework. Many more components are provided by third-party
modules and extensions.
2018-05-29 06:10:52 +02:00
- [GridField_ActionMenu ](api:SilverStripe\Forms\GridField\GridField_ActionMenu )
2017-07-03 03:22:12 +02:00
- [GridFieldToolbarHeader ](api:SilverStripe\Forms\GridField\GridFieldToolbarHeader )
- [GridFieldSortableHeader ](api:SilverStripe\Forms\GridField\GridFieldSortableHeader )
- [GridFieldFilterHeader ](api:SilverStripe\Forms\GridField\GridFieldFilterHeader )
- [GridFieldDataColumns ](api:SilverStripe\Forms\GridField\GridFieldDataColumns )
- [GridFieldDeleteAction ](api:SilverStripe\Forms\GridField\GridFieldDeleteAction )
- [GridFieldViewButton ](api:SilverStripe\Forms\GridField\GridFieldViewButton )
- [GridFieldEditButton ](api:SilverStripe\Forms\GridField\GridFieldEditButton )
- [GridFieldExportButton ](api:SilverStripe\Forms\GridField\GridFieldExportButton )
- [GridFieldPrintButton ](api:SilverStripe\Forms\GridField\GridFieldPrintButton )
- [GridFieldPaginator ](api:SilverStripe\Forms\GridField\GridFieldPaginator )
- [GridFieldDetailForm ](api:SilverStripe\Forms\GridField\GridFieldDetailForm )
2014-10-19 10:32:34 +02:00
## Bundled GridFieldConfig
As a shortcut, `GridFieldConfig` subclasses can define a list of `GridFieldComponent` objects to use. This saves
developers manually adding each component.
### GridFieldConfig_Base
A simple read-only and paginated view of records with sortable and searchable headers.
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
$config = GridFieldConfig_Base::create();
2014-10-19 10:32:34 +02:00
2017-10-27 04:38:27 +02:00
$gridField->setConfig($config);
2014-10-19 10:32:34 +02:00
2017-10-27 04:38:27 +02:00
// Is the same as adding the following components..
// .. new GridFieldToolbarHeader()
// .. new GridFieldSortableHeader()
// .. new GridFieldFilterHeader()
// .. new GridFieldDataColumns()
// .. new GridFieldPageCount('toolbar-header-right')
// .. new GridFieldPaginator($itemsPerPage)
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
### GridFieldConfig_RecordViewer
Similar to `GridFieldConfig_Base` with the addition support of the ability to view a `GridFieldDetailForm` containing
a read-only view of the data record.
< div class = "info" markdown = "1" >
The data row show must be a `DataObject` subclass. The fields displayed in the read-only view come from
`DataObject::getCMSFields()` .
< / div >
< div class = "alert" markdown = "1" >
The `DataObject` class displayed must define a `canView()` method that returns a boolean on whether the user can view
this record.
< / div >
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
$config = GridFieldConfig_RecordViewer::create();
$gridField->setConfig($config);
2014-10-19 10:32:34 +02:00
2017-10-27 04:38:27 +02:00
// Same as GridFieldConfig_Base with the addition of
// .. new GridFieldViewButton(),
// .. new GridFieldDetailForm()
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
### GridFieldConfig_RecordEditor
Similar to `GridFieldConfig_RecordViewer` with the addition support to edit or delete each of the records.
< div class = "info" markdown = "1" >
The data row show must be a `DataObject` subclass. The fields displayed in the edit view come from
`DataObject::getCMSFields()` .
< / div >
< div class = "alert" markdown = "1" >
Permission control for editing and deleting the record uses the `canEdit()` and `canDelete()` methods on the
`DataObject` object.
< / div >
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
$config = GridFieldConfig_RecordEditor::create();
$gridField->setConfig($config);
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
// Same as GridFieldConfig_RecordViewer with the addition of
// .. new GridFieldAddNewButton(),
// .. new GridFieldEditButton(),
// .. new GridFieldDeleteAction()
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
### GridFieldConfig_RelationEditor
Similar to `GridFieldConfig_RecordEditor` , but adds features to work on a record's has-many or many-many relationships.
2017-08-03 02:51:32 +02:00
As such, it expects the list used with the `GridField` to be a instance of `RelationList` .
2017-10-27 04:38:27 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
$config = GridFieldConfig_RelationEditor::create();
2014-10-19 10:32:34 +02:00
2017-10-27 04:38:27 +02:00
$gridField->setConfig($config);
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
This configuration adds the ability to searched for existing records and add a relationship
(`GridFieldAddExistingAutocompleter`).
Records created or deleted through the `GridFieldConfig_RelationEditor` automatically update the relationship in the
database.
2018-05-29 06:10:52 +02:00
## GridField_ActionMenu
The `GridField_ActionMenu` component provides a dropdown menu which automatically bundles GridField actions into a react based dropdown. It is included by default on `GridFieldConfig_RecordEditor` and `GridFieldConfig_RelationEditor` configs.
To add it to a GridField, add the `GridField_ActionMenu` component and any action(s) that implement `GridField_ActionMenuItem` (such as `GridFieldEditButton` or `GridFieldDeleteAction` ) to the `GridFieldConfig` .
```php
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
// `GridFieldConfig::create()` will create an empty configuration (no components).
$config = GridFieldConfig::create();
// add a component
$config->addComponent();
$config->addComponents(
new GridFieldDataColumns(),
new GridFieldEditButton(),
new GridField_ActionMenu()
);
// Update the GridField with our custom configuration
$gridField->setConfig($config);
```
2014-10-19 10:32:34 +02:00
## GridFieldDetailForm
The `GridFieldDetailForm` component drives the record viewing and editing form. It takes its' fields from
2016-03-30 02:17:28 +02:00
`DataObject->getCMSFields()` method but can be customised to accept different fields via the
2017-07-03 03:22:12 +02:00
[GridFieldDetailForm::setFields() ](api:SilverStripe\Forms\GridField\GridFieldDetailForm::setFields( )) method.
2014-10-19 10:32:34 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldDetailForm;
$form = $gridField->getConfig()->getComponentByType(GridFieldDetailForm::class);
$form->setFields(new FieldList(
new TextField('Title')
));
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
### many_many_extraFields
The component also has the ability to load and save data stored on join tables when two records are related via a
2017-07-03 03:22:12 +02:00
"many_many" relationship, as defined through [DataObject::$many_many_extraFields ](api:SilverStripe\ORM\DataObject::$many_many_extraFields ). While loading and saving works
2014-10-19 10:32:34 +02:00
transparently, you need to add the necessary fields manually, they're not included in the `getCMSFields()` scaffolding.
These extra fields act like usual form fields, but need to be "namespaced" in order for the `GridField` logic to detect
them as fields for relation extra data, and to avoid clashes with the other form fields.
The namespace notation is `ManyMany[<extradata-field-name>]` , so for example `ManyMany[MyExtraField]` .
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
use SilverStripe\ORM\DataObject;
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
class Team extends DataObject
{
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
private static $db = [
'Name' => 'Text'
];
public static $many_many = [
'Players' => 'Player'
];
}
class Player extends DataObject
{
private static $db = [
'Name' => 'Text'
];
public static $many_many = [
'Teams' => 'Team'
];
public static $many_many_extraFields = [
'Teams' => [
'Position' => 'Text'
]
];
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
public function getCMSFields()
{
$fields = parent::getCMSFields();
if($this->ID) {
$teamFields = singleton('Team')->getCMSFields();
$teamFields->addFieldToTab(
'Root.Main',
// The "ManyMany[< extradata-name > ]" convention
new TextField('ManyMany[Position]', 'Current Position')
);
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
$config = GridFieldConfig_RelationEditor::create();
$config->getComponentByType('GridFieldDetailForm')->setFields($teamFields);
2017-08-07 05:11:17 +02:00
2017-10-27 04:38:27 +02:00
$gridField = new GridField('Teams', 'Teams', $this->Teams(), $config);
$fields->findOrMakeTab('Root.Teams')->replaceField('Teams', $gridField);
2017-08-07 05:11:17 +02:00
}
2017-08-03 05:35:09 +02:00
2017-10-27 04:38:27 +02:00
return $fields;
}
}
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
## Flexible Area Assignment through Fragments
`GridField` layouts can contain many components other than the table itself, for example a search bar to find existing
relations, a button to add those, and buttons to export and print the current data. The `GridField` has certain defined
areas called `fragments` where these components can be placed.
The goal is for multiple components to share the same space, for example a header row. The built-in components:
- `header` /`footer`: Renders in a `<thead>` /`< tfoot > `, should contain table markup
- `before` /`after`: Renders before/after the actual `<table>`
- `buttons-before-left` /`buttons-before-right`/`buttons-after-left`/`buttons-after-right`:
2017-07-03 03:22:12 +02:00
Renders in a shared row before the table. Requires [GridFieldButtonRow ](api:SilverStripe\Forms\GridField\GridFieldButtonRow ).
2014-10-19 10:32:34 +02:00
These built-ins can be used by passing the fragment names into the constructor of various components. Note that some
2017-07-03 03:22:12 +02:00
[GridFieldConfig ](api:SilverStripe\Forms\GridField\GridFieldConfig ) classes will already have rows added to them. The following example will add a print button at the
2014-10-19 10:32:34 +02:00
bottom right of the table.
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridFieldButtonRow;
use SilverStripe\Forms\GridField\GridFieldPrintButton;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
$config->addComponent(new GridFieldButtonRow('after'));
$config->addComponent(new GridFieldPrintButton('buttons-after-right'));
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
### Creating your own Fragments
Fragments are designated areas within a `GridField` which can be shared between component templates. You can define
your own fragments by using a `\$DefineFragment' placeholder in your components' template. This example will simply
create an area rendered before the table wrapped in a simple `<div>` .
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
class MyAreaComponent implements GridField_HTMLProvider
{
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
public function getHTMLFragments( $gridField)
2017-08-07 05:11:17 +02:00
{
2017-10-27 04:38:27 +02:00
return [
'before' => '< div class = "my-area" > $DefineFragment(my-area)< / div > '
];
2017-08-07 05:11:17 +02:00
}
2017-10-27 04:38:27 +02:00
}
2017-08-03 05:35:09 +02:00
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
< div class = "notice" markdown = "1" >
Please note that in templates, you'll need to escape the dollar sign on `\$DefineFragment` . These are specially
processed placeholders as opposed to native template syntax.
< / div >
Now you can add other components into this area by returning them as an array from your
2017-07-03 03:22:12 +02:00
[GridFieldComponent::getHTMLFragments() ](api:SilverStripe\Forms\GridField\GridFieldComponent::getHTMLFragments( )) implementation:
2014-10-19 10:32:34 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-10-27 04:38:27 +02:00
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
2017-10-26 02:22:02 +02:00
2017-10-27 04:38:27 +02:00
class MyShareLinkComponent implements GridField_HTMLProvider
{
public function getHTMLFragments( $gridField)
{
return [
'my-area' => '< a href > ...< / a > '
];
2017-08-07 05:11:17 +02:00
}
2017-10-27 04:38:27 +02:00
}
2017-08-03 05:35:09 +02:00
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
2017-07-03 03:22:12 +02:00
Your new area can also be used by existing components, e.g. the [GridFieldPrintButton ](api:SilverStripe\Forms\GridField\GridFieldPrintButton )
2014-10-19 10:32:34 +02:00
2017-08-03 02:51:32 +02:00
```php
2017-11-17 03:11:05 +01:00
new GridFieldPrintButton('my-area');
2017-08-03 02:51:32 +02:00
```
2014-10-19 10:32:34 +02:00
## Creating a Custom GridFieldComponent
Customizing a `GridField` is easy, applications and modules can provide their own `GridFieldComponent` instances to add
2015-05-05 13:13:08 +02:00
functionality. See [How to Create a GridFieldComponent ](../how_tos/create_a_gridfieldcomponent ).
2014-10-19 10:32:34 +02:00
## Creating a Custom GridField_ActionProvider
2017-07-03 03:22:12 +02:00
[GridField_ActionProvider ](api:SilverStripe\Forms\GridField\GridField_ActionProvider ) provides row level actions such as deleting a record. See
2014-10-19 10:32:34 +02:00
[How to Create a GridField_ActionProvider ](../how_tos/create_a_gridfield_actionprovider ).
## Saving the GridField State
`GridState` is a class that is used to contain the current state and actions on the `GridField` . It's transfered
between page requests by being inserted as a hidden field in the form.
The `GridState_Component` sets and gets data from the `GridState` .
## API Documentation
2017-07-03 03:22:12 +02:00
* [GridField ](api:SilverStripe\Forms\GridField\GridField )
* [GridFieldConfig ](api:SilverStripe\Forms\GridField\GridFieldConfig )
* [GridFieldComponent ](api:SilverStripe\Forms\GridField\GridFieldComponent )