Skip to content

Commit 2988691

Browse files
committed
DOC Document new ChildFieldManager interface
1 parent 02bcc4d commit 2988691

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
title: ChildFieldManager
3+
summary: Strict management of child fields for advanced use cases
4+
---
5+
6+
# `ChildFieldManager`
7+
8+
In most cases, child form fields can be grouped with a [`CompositeField`](api:SilverStripe\Forms\CompositeField) or one of its subclasses - but sometimes you need more control.
9+
10+
For example, you may have a use case where specific form fields *must* be present in the child field list. In that case you won't want methods like [`FieldList::removeByName()`](api:SilverStripe\Forms\FieldList::removeByName()) or [`FieldList::replaceField()`](api:SilverStripe\Forms\FieldList::replaceField()) to know about your child fields, but you'll still want to expose them for things like [`Form::validate()`](api:SilverStripe\Forms\Form::validate()), [`Form::loadDataFrom()`](api:SilverStripe\Forms\Form::loadDataFrom()), [`Form::saveInto()`](api:SilverStripe\Forms\Form::saveInto()), and allow them to manage their own AJAX requests.
11+
12+
To achieve this, your custom [`FormField`](api:SilverStripe\Forms\FormField) can implement the [`ChildFieldManager`](api:SilverStripe\Forms\ChildFieldManager) interface. The methods declared in this interface allow the form to access your fields for critical functionality, but doesn't let anyone remove or replace fields in your managed child field list.
13+
14+
In order to get managed fields from a `FieldList`, call [`FieldList::getAllDataFields()`](api:SilverStripe\Forms\FieldList::getAllDataFields()). This differs from [`FieldList::dataFields()`](api:SilverStripe\Forms\FieldList::dataFields()) in two ways:
15+
16+
1. It gets all data fields *including* those managed by a `ChildFieldManager`, which `dataFields()` excludes
17+
1. It only caches the same fields that `dataFields()` caches - i.e. fields returned from a `ChildFieldManager` are not cached when calling `getAllDataFields()`.
18+
19+
A very simple implementation of this interface would look like this:
20+
21+
> [!WARNING]
22+
> The below example shows a minimal PHP implementation but not the template.
23+
> The assumption is if you're implementing this interface, you already have an advanced use case and know what you need to do in your template to get your use case broadly working.
24+
25+
```php
26+
namespace App\Form;
27+
28+
use SilverStripe\Forms\ChildFieldManager;
29+
use SilverStripe\Forms\FormField;
30+
use SilverStripe\Forms\TextField;
31+
32+
class MyChildFieldManager extends FormField implements ChildFieldManager
33+
{
34+
private array $children = [];
35+
36+
public function __construct()
37+
{
38+
$this->children = [
39+
'FieldOne' => TextField::create('FieldOne'),
40+
'FieldTwo' => TextField::create('FieldTwo'),
41+
];
42+
parent::__construct('MyManagedField');
43+
}
44+
45+
public function isManagedField(string $fieldName): bool
46+
{
47+
return array_key_exists($fieldName, $this->children);
48+
}
49+
50+
public function getManagedFieldByName(string $fieldName): ?FormField
51+
{
52+
return $this->children[$fieldName] ?? null;
53+
}
54+
55+
public function getManagedFields(): iterable
56+
{
57+
return $this->children;
58+
}
59+
60+
public function getSchemaDataDefaults(): array
61+
{
62+
$defaults = parent::getSchemaDataDefaults();
63+
// Include child schema data for react forms
64+
$children = $this->getChildren();
65+
foreach ($children as $child) {
66+
$childSchema[] = $child->getSchemaData();
67+
}
68+
$defaults['children'] = $childSchema;
69+
return $defaults;
70+
}
71+
}
72+
```
73+
74+
You can then implement whatever logic you want and rely on those specific fields being there no matter what anyone else is doing with your form.
75+
76+
> [!TIP]
77+
> It's usually a good idea to ensure that if [`FormField::setForm()`](api:SilverStripe\Forms\FormField::setForm()), [`FormField::performReadonlyTransformation()`](api:SilverStripe\Forms\FormField::performReadonlyTransformation()), [`FormField::performDisabledTransformation()`](api:SilverStripe\Forms\FormField::performDisabledTransformation()), [`FormField::setReadonly()`](api:SilverStripe\Forms\FormField::setReadonly()), or [`FormField::setDisabled()`](api:SilverStripe\Forms\FormField::setDisabled()) is called on your parent form, the appropriate methods are called on your child fields a well.

en/08_Changelogs/6.2.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ You can filter by the name and description of the campaign, its status, and the
135135

136136
### Other new features and enhancements {#other-new}
137137

138+
- A new [`ChildFieldManager`](api:SilverStripe\Forms\ChildFieldManager) interface has been added to allow a parent form field to strictly control its children, but still allow setting/getting values for those fields let them handle AJAX requests. See [`ChildFieldManager` docs](/developer_guides/forms/field_types/childfieldmanager/) for more details.
138139
- The `help` plugin is now added by default to all [`TinyMCEConfig`](api:SilverStripe\TinyMCE\TinyMCEConfig) instances. If you were adding it manually, you can remove that custom code. If for some reason you don't want that plugin in one of your configs, you can use [`TinyMCEConfig::disablePlugins()`](api:SilverStripe\TinyMCE\TinyMCEConfig::disablePlugins()) to remove it - but be aware that it is extremely useful for screen reader users to keep this plugin installed.
139140
- [`HTML::createTag()`](api:SilverStripe\View\HTML::createTag()) now supports value-less boolean attributes. For example if you pass `HTML::create('input', ['readonly' => true])`, the result will be `<input readonly>`. Previously it would output as `<input readonly="1">`.
140141
- The built-in session handlers [`FileSessionHandler`](api:SilverStripe\Control\SessionHandler\FileSessionHandler), [`CacheSessionHandler`](api:SilverStripe\Control\SessionHandler\CacheSessionHandler), and [`DatabaseSessionHandler`](api:SilverStripe\Control\SessionHandler\DatabaseSessionHandler) all now validate the session ID `PHPSESSID` to ensure it matches a valid format, otherwise a `RuntimeException` will be thrown.

0 commit comments

Comments
 (0)