Skip to content

Commit

Permalink
Merge branch '4' into 5
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Jun 11, 2024
2 parents 515c2b4 + edb3442 commit 66d8c51
Show file tree
Hide file tree
Showing 5 changed files with 486 additions and 24 deletions.
31 changes: 31 additions & 0 deletions behat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Run silverstripe-gridfieldextensions behat tests with this command
# Note that silverstripe-gridfieldextensions behat tests require CMS module
# ========================================================================= #
# chromedriver
# vendor/bin/behat @silverstripe-gridfieldextensions
# ========================================================================= #
default:
suites:
silverstripe-gridfieldextensions:
paths:
- '%paths.modules.silverstripe-gridfieldextensions%/tests/behat/features'
contexts:
- SilverStripe\Framework\Tests\Behaviour\FeatureContext
- SilverStripe\Framework\Tests\Behaviour\CmsFormsContext
- SilverStripe\Framework\Tests\Behaviour\CmsUiContext
- SilverStripe\BehatExtension\Context\BasicContext
- SilverStripe\BehatExtension\Context\LoginContext
- SilverStripe\BehatExtension\Context\FixtureContext:
- '%paths.modules.silverstripe-gridfieldextensions%/tests/behat/features/files/'

extensions:
SilverStripe\BehatExtension\MinkExtension:
default_session: facebook_web_driver
javascript_session: facebook_web_driver
facebook_web_driver:
browser: chrome
wd_host: "http://127.0.0.1:9515" #chromedriver port

SilverStripe\BehatExtension\Extension:
screenshot_path: '%paths.base%/artifacts/screenshots'
bootstrap_file: vendor/silverstripe/framework/tests/behat/serve-bootstrap.php
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"squizlabs/php_codesniffer": "^3.7",
"silverstripe/versioned": "^3",
"silverstripe/standards": "^1",
"phpstan/extension-installer": "^1.3"
"phpstan/extension-installer": "^1.3",
"silverstripe/frameworktest": "^2"
},
"extra": {
"screenshots": [
Expand Down
272 changes: 249 additions & 23 deletions docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,39 +159,265 @@ Nested GridFields
The `GridFieldNestedForm` component allows you to nest GridFields in the UI. It can be used with `DataObject` subclasses
with the `Hierarchy` extension, or by specifying the relation used for nesting.

Here is a small example of basic use of Nested GridField.

```php
// Basic usage, defaults to the Children-method for Hierarchy objects.
$grid->getConfig()->addComponent(GridFieldNestedForm::create());
namespace App\Admin;

use MyObject;
use SilverStripe\Admin\ModelAdmin;
use Symbiote\GridFieldExtensions\GridFieldNestedForm;

class MyAdmin extends ModelAdmin
{
//...

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

$grid = $form->Fields()->dataFieldByName(MyObject::class);
// Add Nested GridField to main GridField
$grid->getConfig()->addComponent(GridFieldNestedForm::create());

// Usage with custom relation
$grid->getConfig()->addComponent(GridFieldNestedForm::create()->setRelationName('MyRelation'));
return $form;
}
}
```

You can define your own custom GridField config for the nested GridField configuration by implementing a `getNestedConfig`
on your nested model (should return a `GridField_Config` object).
There are several ways to use Nested GridField. The implementation depends on the type of data you will be using in your GridField.
For instance, if there is a `DataObject` that has the `Hierarchy` extension, you can use the following approach.

As an example, here we can use a typical hierarchy of the `Group` model, where another `Group` can serve as a parent.

```php
class NestedObject extends DataObject
namespace App\Extensions;

use SilverStripe\Core\Extension;
use SilverStripe\Security\Group;
use Symbiote\GridFieldExtensions\GridFieldNestedForm;

class MySecurityAdminExtension extends Extension
{
private static $has_one = [
'Parent' => ParentObject::class
];

public function getNestedConfig(): GridFieldConfig
{
$config = new GridFieldConfig_RecordViewer();
return $config;
}
public function updateGridFieldConfig($config)
{
if ($this->owner->getModelClass() === Group::class) {
$config->addComponent(GridFieldNestedForm::create());
}
}
}
```

You can also modify the default config (a `GridFieldConfig_RecordEditor`) via an extension to the nested model class, by implementing
`updateNestedConfig`, which will get the config object as the first parameter.
Or also view a list of all members of a given group. Notice we call `setRelationName()` to explicitly state the relation which should be displayed in the Nested GridField.

```php
class NestedObjectExtension extends DataExtension
namespace App\Extensions;

use SilverStripe\Core\Extension;
use SilverStripe\Security\Group;
use Symbiote\GridFieldExtensions\GridFieldNestedForm;

class MySecurityAdminExtension extends Extension
{
public function updateNestedConfig(GridFieldConfig &$config)
{
$config->removeComponentsByType(GridFieldPaginator::class);
}
public function updateGridFieldConfig($config)
{
if ($this->owner->getModelClass() === Group::class) {
$config->addComponent(GridFieldNestedForm::create()->setRelationName('Members'));
}
}
}
```

```yml
SilverStripe\Admin\SecurityAdmin:
extensions:
- App\Extensions\MySecurityAdminExtension
```
Another way to use Nested GridField together with `DataObjects` that do not have the `Hierarchy` extension but have `has_many` relationships with other objects.
Let's say you have the following `DataObject` that has multiple levels of relationships, and an admin section where the data of this object will be displayed.
You want the user to be able to view information regarding this object and all nested objects on the same page, without the need to navigate to each object individually.
In this case, you can use the following approach.

```php
namespace App\Models;
use SilverStripe\ORM\DataObject;
class ParentNode extends DataObject
{
//...
private static $has_many = [
'ChildNodes' => BranchNode::class,
];
}
```

You can define your own custom GridField config for the nested GridField configuration by implementing a `getNestedConfig()` method on your nested model. Notice this method should return a `GridFieldConfig` object.

```php
namespace App\Models;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\ORM\DataObject;
use Symbiote\GridFieldExtensions\GridFieldNestedForm;
class ChildNode extends DataObject
{
//...
private static $has_one = [
'ParentNode' => ParentNode::class,
];
private static $has_many = [
'GrandChildNodes' => GrandChildNode::class,
];
public function getNestedConfig(): GridFieldConfig
{
$config = new GridFieldConfig_RecordEditor();
$config->addComponent(GridFieldNestedForm::create()->setRelationName('GrandChildNodes'));
return $config;
}
}
```

```php
namespace App\Models;
use SilverStripe\ORM\DataObject;
class GrandChildNode extends DataObject
{
//...
private static $has_one = [
'ChildNode' => ChildNode::class,
];
}
```

```php
namespace App\Admin;
use App\Models\ParentNode;
use SilverStripe\Admin\ModelAdmin;
use SilverStripe\Forms\GridField\GridFieldConfig;
use Symbiote\GridFieldExtensions\GridFieldNestedForm;
class MyAdminSection extends ModelAdmin
{
private static string $url_segment = 'my-admin-section';
private static string $menu_title = 'My Admin Section';
private static array $managed_models = [
ParentNode::class
];
protected function getGridFieldConfig(): GridFieldConfig
{
$config = parent::getGridFieldConfig();
$config->addComponent(GridFieldNestedForm::create()->setRelationName('ChildNodes'));
return $config;
}
}
```

There is also the possibility to use Nested GridField with the data structure ArrayList. To do this, you can use the following approach.

```php
namespace App\Models;
use MyDataObject;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
class MyDataSet extends DataObject
{
//...
public function getMyArrayList() {
$list = ArrayList::create();
$data = MyDataObject::get();
foreach ($data as $value) {
$list->push($value);
}
return $list;
}
}
```

```php
namespace App\Admin;
use App\Models\MyDataSet;
use SilverStripe\Admin\ModelAdmin;
use SilverStripe\Forms\GridField\GridFieldConfig;
use Symbiote\GridFieldExtensions\GridFieldNestedForm;
class MyAdminSection extends ModelAdmin
{
//...
private static array $managed_models = [
MyDataSet::class
];
protected function getGridFieldConfig(): GridFieldConfig
{
$config = parent::getGridFieldConfig();
$config->addComponent(GridFieldNestedForm::create()->setRelationName('getMyArrayList'));
return $config;
}
}
```

Notice that instead of the name of a relation, we're passing a method name into `getMyArrayList()`. That method must return an instance of `SS_List` to be used in the GridField.


#### Additional features and settings

1. You can set the maximum number of nested levels using a `$default_max_nesting_level` configuration property. The default value is 10 levels.

```yml
Symbiote\GridFieldExtensions\GridFieldNestedForm:
default_max_nesting_level: 5
```

You can also set this limit for a specific nested GridField using the `setMaxNestingLevel()` method.

```php
public function getNestedConfig(): GridFieldConfig
{
$config = new GridFieldConfig_RecordEditor();
$config->addComponent(GridFieldNestedForm::create()->setMaxNestingLevel(5));
return $config;
}
```

1. You can also modify the default config (a `GridFieldConfig_RecordEditor`) via an extension to the nested model class, by implementing
`updateNestedConfig`, which will get the config object as the parameter.

```php
namespace App\Extensions;
use SilverStripe\Core\Extension;
class NestedObjectExtension extends Extension
{
public function updateNestedConfig(GridFieldConfig &$config)
{
$config->removeComponentsByType(GridFieldPaginator::class);
}
}
```
Loading

0 comments on commit 66d8c51

Please sign in to comment.