silverstripe-framework/docs/en/02_Developer_Guides/03_Forms/How_Tos/01_Encapsulate_Forms.md

184 lines
5.2 KiB
Markdown
Raw Normal View History

---
title: How to Encapsulate Forms
summary: Learn how to move a form from a controller into its own class definition.
iconBrand: wpforms
---
# How to Encapsulate Forms
Form definitions can often get long, complex and often end up cluttering up a `Controller` definition. We may also want
to reuse the `Form` across multiple `Controller` classes rather than just one. A nice way to encapsulate the logic and
code for a `Form` is to create it as a subclass to `Form`. Let's look at a example of a `Form` which is on our
`Controller` but would be better written as a subclass.
**app/src/Page.php**
```php
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\HeaderField;
use SilverStripe\Forms\OptionsetField;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\CheckboxSetField;
use SilverStripe\Forms\NumericField;
use SilverStripe\Forms\FormAction;
use SilverStripe\CMS\Controllers\ContentController;
class PageController extends ContentController
{
public function SearchForm()
2017-08-07 05:11:17 +02:00
{
$fields = new FieldList(
HeaderField::create('Header', 'Step 1. Basics'),
OptionsetField::create('Type', '', [
'foo' => 'Search Foo',
'bar' => 'Search Bar',
'baz' => 'Search Baz'
]),
CompositeField::create(
HeaderField::create('Header2', 'Step 2. Advanced '),
CheckboxSetField::create('Foo', 'Select Option', [
'qux' => 'Search Qux'
]),
CheckboxSetField::create('Category', 'Category', [
'Foo' => 'Foo',
'Bar' => 'Bar'
2017-08-07 05:11:17 +02:00
]),
NumericField::create('Minimum', 'Minimum'),
NumericField::create('Maximum', 'Maximum')
)
);
2017-08-07 05:11:17 +02:00
$actions = new FieldList(
FormAction::create('doSearchForm', 'Search')
);
$required = new RequiredFields([
'Type'
]);
2017-08-07 05:11:17 +02:00
$form = new Form($this, 'SearchForm', $fields, $actions, $required);
$form->setFormMethod('GET');
$form->addExtraClass('no-action-styles');
$form->disableSecurityToken();
$form->loadDataFrom($_REQUEST);
return $form;
2017-08-07 05:11:17 +02:00
}
}
2017-08-03 05:35:09 +02:00
```
Now that is a bit of code to include on our controller and generally makes the file look much more complex than it
should be. Good practice would be to move this to a subclass and create a new instance for your particular controller.
**app/src/forms/SearchForm.php**
```php
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\HeaderField;
use SilverStripe\Forms\OptionsetField;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\CheckboxSetField;
use SilverStripe\Forms\NumericField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\Form;
class SearchForm extends Form
{
/**
* Our constructor only requires the controller and the name of the form
* method. We'll create the fields and actions in here.
*
*/
public function __construct($controller, $name)
2017-08-07 05:11:17 +02:00
{
$fields = new FieldList(
HeaderField::create('Header', 'Step 1. Basics'),
OptionsetField::create('Type', '', [
'foo' => 'Search Foo',
'bar' => 'Search Bar',
'baz' => 'Search Baz'
]),
CompositeField::create(
HeaderField::create('Header2', 'Step 2. Advanced '),
CheckboxSetField::create('Foo', 'Select Option', [
'qux' => 'Search Qux'
]),
2017-08-07 05:11:17 +02:00
CheckboxSetField::create('Category', 'Category', [
'Foo' => 'Foo',
'Bar' => 'Bar'
2017-08-07 05:11:17 +02:00
]),
NumericField::create('Minimum', 'Minimum'),
NumericField::create('Maximum', 'Maximum')
)
);
$actions = new FieldList(
FormAction::create('doSearchForm', 'Search')
);
2017-08-07 05:11:17 +02:00
$required = new RequiredFields([
'Type'
]);
// now we create the actual form with our fields and actions defined
// within this class
parent::__construct($controller, $name, $fields, $actions, $required);
// any modifications we need to make to the form.
$this->setFormMethod('GET');
$this->addExtraClass('no-action-styles');
$this->disableSecurityToken();
$this->loadDataFrom($_REQUEST);
2017-08-07 05:11:17 +02:00
}
}
2017-08-03 05:35:09 +02:00
```
Our controller will now just have to create a new instance of this form object. Keeping the file light and easy to read.
**app/src/Page.php**
```php
use SearchForm;
use SilverStripe\CMS\Controllers\ContentController;
class PageController extends ContentController
{
private static $allowed_actions = [
'SearchForm',
];
public function SearchForm()
2017-08-07 05:11:17 +02:00
{
return new SearchForm($this, 'SearchForm');
2017-08-07 05:11:17 +02:00
}
}
```
Form actions can also be defined within your `Form` subclass to keep the entire form logic encapsulated.
## Related Documentation
* [Introduction to Forms](../introduction)
## API Documentation
* [Form](api:SilverStripe\Forms\Form)