2011-02-07 07:48:44 +01:00
# Forms
## Introduction
2012-03-24 22:16:59 +01:00
Form is the base class of all forms in a SilverStripe application. Forms in your application can be created either by
2011-02-07 07:48:44 +01:00
instantiating the Form class itself, or by subclassing it.
## Instantiating a form
Creating a form is a matter of defining a method to represent that form. This method should return a form object. The
constructor takes the following arguments:
* `$controller` : This must be the controller that contains the form.
* `$name` : This must be the name of the method on that controller that is called to return the form. The first two
fields allow the form object to be re-created after submission. **It's vital that they are properly set - if you ever
have problems with form action handler not working, check that these values are correct.**
2011-10-28 03:37:27 +02:00
* `$fields` : A `[api:FieldList]` containing `[api:FormField]` instances make up fields in the form.
* `$actions` : A `[api:FieldList]` containing the `[api:FormAction]` objects - the buttons at the bottom.
2011-02-07 07:48:44 +01:00
* `$validator` : An optional `[api:Validator]` for more information.
Example:
:::php
2012-01-30 23:13:42 +01:00
public function MyCustomForm() {
2011-10-28 03:37:27 +02:00
$fields = new FieldList(
2011-02-07 07:48:44 +01:00
new EmailField("Email"),
new EncryptField("Password")
);
2011-10-28 03:37:27 +02:00
$actions = new FieldList(new FormAction("login", "Log in"));
2011-02-07 07:48:44 +01:00
return new Form($this, "MyCustomForm", $fields, $actions);
}
## Subclassing a form
2011-03-08 22:05:51 +01:00
It's the responsibility of your subclass' constructor to call
2011-02-07 07:48:44 +01:00
:::php
parent::__construct()
with the right parameters. You may choose to take $fields and $actions as arguments if you wish, but $controller and
$name must be passed - their values depend on where the form is instantiated.
:::php
class MyForm extends Form {
2012-01-30 23:13:42 +01:00
public function __construct($controller, $name) {
2011-10-28 03:37:27 +02:00
$fields = new FieldList(
2011-02-07 07:48:44 +01:00
new EmailField("Email"),
new EncryptedField("Password")
);
2011-10-28 03:37:27 +02:00
$actions = new FieldList(new FormAction("login", "Log in"));
2011-02-07 07:48:44 +01:00
parent::__construct($controller, $name, $fields, $actions);
}
}
The real difference, however, is that you can then define your controller methods within the form class itself.
2011-03-08 22:05:51 +01:00
2011-02-07 07:48:44 +01:00
## Form Field Types
2012-06-28 11:43:56 +02:00
There are many classes extending `[api:FormField]` ,
there's a full overview at [form-field-types ](/reference/form-field-types )
2011-02-07 07:48:44 +01:00
2011-03-08 22:05:51 +01:00
2011-02-07 07:48:44 +01:00
### Using Form Fields
2012-06-28 11:43:56 +02:00
To get these fields automatically rendered into a form element,
all you need to do is create a new instance of the
2011-10-28 03:37:27 +02:00
class, and add it to the fieldlist of the form.
2011-02-07 07:48:44 +01:00
:::php
$form = new Form(
2012-06-28 11:43:56 +02:00
$this, // controller
"SignupForm", // form name
new FieldList( // fields
TextField::create("FirstName")
->setTitle('First name')
TextField::create("Surname")
->setTitle('Last name')
->setMaxLength(50),
EmailField::create("Email")
->setTitle("Email address")
->setAttribute('type', 'email')
),
new FieldList( // actions
FormAction::create("signup")->setTitle("Sign up")
),
new RequiredFields( // validation
"Email", "FirstName"
)
2011-02-07 07:48:44 +01:00
);
2012-06-28 11:43:56 +02:00
You'll notice that we've used a new notation for creating form fields,
using `create()` instead of the `new` operator. These are functionally equivalent,
but allows PHP to chain operations like `setTitle()` without assigning
the field instance to a temporary variable.
2011-02-07 07:48:44 +01:00
## Readonly
Readonly on a Form
:::php
$myForm->makeReadonly();
2011-10-28 03:37:27 +02:00
Readonly on a FieldList
2011-02-07 07:48:44 +01:00
:::php
2012-06-28 11:43:56 +02:00
$myFieldList->makeReadonly();
2011-02-07 07:48:44 +01:00
Readonly on a FormField
:::php
$myReadonlyField = $myField->transform(new ReadonlyTransformation());
// shortcut
$myReadonlyField = $myField->performReadonlyTransformation();
2011-12-22 14:56:38 +01:00
## Custom form templates
2011-02-07 07:48:44 +01:00
You can use a custom form template to render with, instead of *Form.ss*
It's recommended you only do this if you've got a lot of presentation text, graphics that surround the form fields. This
is better than defining those as *LiteralField* objects, as it doesn't clutter the data layer with presentation junk.
First of all, you need to create your form on it's own class, that way you can define a custom template using a `forTemplate()` method on your Form class.
:::php
class MyForm extends Form {
2012-06-28 11:43:56 +02:00
public function __construct($controller, $name) {
$fields = new FieldList(
new TextField('FirstName', 'First name'),
new EmailField('Email', 'Email address')
);
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
$actions = new FieldList(
new FormAction('submit', 'Submit')
);
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
parent::__construct($controller, $name, $fields, $actions);
}
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
public function forTemplate() {
return $this->renderWith(array(
$this->class,
'Form'
));
}
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
public function submit($data, $form) {
// do stuff here
}
2011-02-07 07:48:44 +01:00
}
2011-03-08 22:05:51 +01:00
`forTemplate()` tells the `[api:Form]` class to render with a template of return value of `$this->class` , which in this case
is *MyForm* , the name of the class. If the template doesn't exist, then it falls back to using Form.ss.
2011-02-07 07:48:44 +01:00
*MyForm.ss* should then be placed into your *templates/Includes* directory for your project. Here is an example of
basic customisation:
:::ss
< form $ FormAttributes >
2012-06-28 11:43:56 +02:00
< % if Message %>
< p id = "{$FormName}_error" class = "message $MessageType" > $Message< / p >
< % else %>
< p id = "{$FormName}_error" class = "message $MessageType" style = "display: none" > < / p >
< % end_if %>
< fieldset >
< div id = "FirstName" class = "field text" >
< label class = "left" for = "{$FormName}_FirstName" > First name< / label >
$dataFieldByName(FirstName)
< / div >
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
< div id = "Email" class = "field email" >
< label class = "left" for = "{$FormName}_Email" > Email< / label >
$dataFieldByName(Email)
< / div >
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
$dataFieldByName(SecurityID)
< / fieldset >
2011-02-07 07:48:44 +01:00
2012-06-28 11:43:56 +02:00
< % if Actions %>
< div class = "Actions" >
< % loop Actions %>$Field< % end_loop %>
< / div >
< % end_if %>
2011-02-07 07:48:44 +01:00
< / form >
`$dataFieldByName(FirstName)` will return the form control contents of `Field()` for the particular field object, in
this case `TextField->Field()` or `EmailField->Field()` which returns an `<input>` element with specific markup
for the type of field. Pass in the name of the field as the first parameter, as done above, to render it into the
template.
2011-03-08 22:05:51 +01:00
To find more methods, have a look at the `[api:Form]` class, as there is a lot of different methods of customising the form
2012-06-26 17:32:46 +02:00
templates, for example, you could use `<% loop Fields %>` instead of specifying each field manually, as we've done
2011-02-07 07:48:44 +01:00
above.
2011-12-22 14:56:38 +01:00
### Custom form field templates
The easiest way to customize form fields is adding CSS classes and additional attributes.
:::php
$field = new TextField('MyText');
$field->addExtraClass('largeText');
$field->setAttribute('data-validation-regex', '[\d]*');
// Field() renders as:
// < input type = "text" class = "largeText" id = "Form_Form_TextField" name = "TextField" data-validation-regex = "[ \d]*" >
Each form field is rendered into a form via the `[FieldHolder()](api:FormField->FieldHolder())` method,
which includes a container `<div>` as well as a `<label>` element (if applicable).
You can also render each field without these structural elements through the `[Field()](api:FormField->Field())` method.
In order to influence the form rendering, overloading these two methods is a good start.
2012-03-24 22:16:59 +01:00
In addition, most form fields are rendered through SilverStripe templates, e.g. `TextareaField` is rendered via `framework/templates/forms/TextareaField.ss` .
2011-12-22 14:56:38 +01:00
These templates can be overwritten globally by placing a template with the same name in your `mysite` directory,
or set on a form field instance via `[setTemplate()](api:FormField->setTemplate())` and `[setFieldHolderTemplate()](api:FormField->setFieldHolderTemplate())` .
2011-02-07 07:48:44 +01:00
### Securing forms against Cross-Site Request Forgery (CSRF)
SilverStripe tries to protect users against *Cross-Site Request Forgery (CSRF)* by adding a hidden *SecurityID*
parameter to each form. See [secure-development ](/topics/security ) for details.
### Remove existing fields
If you want to remove certain fields from your subclass:
:::php
class MyCustomForm extends MyForm {
2012-01-30 23:13:42 +01:00
public function __construct($controller, $name) {
2011-02-07 07:48:44 +01:00
parent::__construct($controller, $name);
// remove a normal field
$this->fields->removeByName('MyFieldName');
// remove a field from a tab
$this->fields->removeFieldFromTab('TabName', 'MyFieldName');
}
}
### Working with tabs
Adds a new text field called FavouriteColour next to the Content field in the CMS
:::php
2011-04-15 06:36:22 +02:00
$fields->addFieldToTab('Root.Content', new TextField('FavouriteColour'), 'Content');
2011-02-07 07:48:44 +01:00
## Related
2011-06-06 04:25:41 +02:00
* [Form Field Types ](/reference/form-field-types )
* [MultiForm Module ](http://silverstripe.org/multi-form-module )
2011-02-07 07:48:44 +01:00
## API Documentation
2011-06-06 04:25:41 +02:00
* `[api:Form]`
* `[api:FormField]`
2011-10-28 03:37:27 +02:00
* `[api:FieldList]`
2012-03-24 22:16:59 +01:00
* `[api:FormAction]`