Create form field SilverStripe
August 20, 2025 · AI Conversations
$Title
in silver stripe cms
### 1) Add the field to your form (PHP)
use SilverStripeFormsFieldList;
use SilverStripeFormsForm;
use SilverStripeFormsOptionsetField;
use SilverStripeFormsFormAction;
use SilverStripeFormsRequiredFields;
public function MyForm()
{
$quality = OptionsetField::create(
'QualitatDerWohnung',
'Qualität der Wohnung',
[
'option1' => 'option1',
'option2' => 'option2',
'option3' => 'option3',
]
)
// optional: preselect a value
->setValue('option2')
// optional: add HTML "required" attribute
->setAttribute('required', 'required');
$fields = FieldList::create($quality);
$actions = FieldList::create(FormAction::create('doSubmit', 'Save'));
$validator = RequiredFields::create(['QualitatDerWohnung']); // server-side required
return Form::create($this, 'MyForm', $fields, $actions, $validator);
}
### 2) Provide a custom template for `OptionsetField`
Create this file (either approach):
– **Override globally for all option sets:**
`app/templates/SilverStripe/Forms/OptionsetField.ss`
– **Only for this field:** create a subclass (e.g. `MyOptionsetField extends OptionsetField`) and name the template `MyOptionsetField.ss`, then call `->setTemplate('MyOptionsetField')`.
**Template contents (`OptionsetField.ss` or `MyOptionsetField.ss`):**
<ul class="double_column">
<% loop $Options %>
<li>
<div class="radio_group d-flex">
$Title
<label class="radio-wrapper">
<input type="radio"
name="$Name"
value="$Value"
id="$ID"
$AttributesHTML
<% if $isChecked %>checked="checked"<% end_if %> />
<span class="custom-radio"></span>
</label>
</div>
</li>
<% end_loop %>
</ul>
> Notes:
> – `$Options`, `$Title`, `$Name`, `$Value`, `$ID`, `$isChecked`, and `$AttributesHTML` are the standard variables available in the `OptionsetField` template—so your snippet is perfect.
> – If you used a subclass (e.g., `MyOptionsetField`), add in PHP:
> `->setTemplate('MyOptionsetField')`
### 3) Flush templates
After adding the template, hit your site with `?flush=all` (e.g., `/my-page/MyForm?flush=all`) to clear the template cache.
That’s it—your radios will render with exactly the HTML you posted, wired to a proper SilverStripe form field and validation.
$Title
$Title
Here are two clean ways to do it.
—
# Option A — Subclass per layout (most reusable)
### 1) Create two tiny subclasses
// app/src/Form/InlineOptionsetField.php
namespace AppForm;
use SilverStripeFormsOptionsetField;
class InlineOptionsetField extends OptionsetField {}
// app/src/Form/TwoColOptionsetField.php
namespace AppForm;
use SilverStripeFormsOptionsetField;
class TwoColOptionsetField extends OptionsetField {}
### 2) Add templates
Create these files under `app/templates/`:
**`InlineOptionsetField_holder.ss`** (your “label + inline radios” layout)
<div class="radio_group">
<label class="form-label">$Title</label>
<div class="d-flex">
<% loop $Options %>
<label class="radio-wrapper">
<input type="radio"
name="$Name"
value="$Value"
id="$ID"
$AttributesHTML
<% if $isChecked %>checked="checked"<% end_if %> />
<span class="custom-radio"></span> $Title
</label>
<% end_loop %>
</div>
<% if $Message %>
<span class="message $MessageType">$Message</span>
<% end_if %>
<% if $RightTitle %><span class="right">$RightTitle</span><% end_if %>
<% if $Description %><p class="description">$Description</p><% end_if %>
</div>
**`TwoColOptionsetField_holder.ss`** (your previous two‑column “ layout)
<div class="radio_group two-col">
<label class="form-label">$Title</label>
<ul class="double_column">
<% loop $Options %>
<li>
<div class="radio_group d-flex">
$Title
<label class="radio-wrapper">
<input type="radio"
name="$Name"
value="$Value"
id="$ID"
$AttributesHTML
<% if $isChecked %>checked="checked"<% end_if %> />
<span class="custom-radio"></span>
</label>
</div>
</li>
<% end_loop %>
</ul>
<% if $Message %>
<span class="message $MessageType">$Message</span>
<% end_if %>
<% if $RightTitle %><span class="right">$RightTitle</span><% end_if %>
<% if $Description %><p class="description">$Description</p><% end_if %>
</div>
*(If you also want to customize the inner radios without the label/wrapper, add `InlineOptionsetField.ss` / `TwoColOptionsetField.ss` similarly.)*
### 3) Use them in your form
use AppFormInlineOptionsetField;
use AppFormTwoColOptionsetField;
$inline = InlineOptionsetField::create(
'QualitatInline',
'Qualität (Inline)',
['option1' => 'option1', 'option2' => 'option2', 'option3' => 'option3']
)->setAttribute('required', 'required');
$twoCol = TwoColOptionsetField::create(
'QualitatTwoCol',
'Qualität (Two Columns)',
['option1' => 'option1', 'option2' => 'option2', 'option3' => 'option3']
);
—
# Option B — Same class, choose templates per instance
If you don’t want subclasses, set the holder template name per field:
$fieldA = OptionsetField::create('QualitatA', 'Qualität (Inline)', $source)
->setFieldHolderTemplate('InlineOptionsetField_holder');
$fieldB = OptionsetField::create('QualitatB', 'Qualität (Two Columns)', $source)
->setFieldHolderTemplate('TwoColOptionsetField_holder');
(Keep the same two `.ss` files from above.)
—
## Don’t forget
– After adding templates: visit any page with `?flush=all`.
– Server‑side “required” is via `RequiredFields`; your `required="required"` attribute is only client‑side.
Pick A (subclasses) if you’ll reuse these layouts often; pick B if you just need per‑field overrides quickly.
Option B — Same class, choose templates per instance
## 1) Create the two holder templates
**`app/templates/InlineOptionsetField_holder.ss`**
<div class="radio_group">
<label class="form-label">$Title</label>
<div class="d-flex">
<% loop $Options %>
<label class="radio-wrapper">
<input type="radio"
name="$Name"
value="$Value"
id="$ID"
$AttributesHTML
<% if $isChecked %>checked="checked"<% end_if %> />
<span class="custom-radio"></span> $Title
</label>
<% end_loop %>
</div>
<% if $Message %><span class="message $MessageType">$Message</span><% end_if %>
<% if $Description %><p class="description">$Description</p><% end_if %>
</div>
**`app/templates/TwoColOptionsetField_holder.ss`**
<div class="radio_group two-col">
<label class="form-label">$Title</label>
<ul class="double_column">
<% loop $Options %>
<li>
<label class="radio-wrapper d-flex">
<input type="radio"
name="$Name"
value="$Value"
id="$ID"
$AttributesHTML
<% if $isChecked %>checked="checked"<% end_if %> />
<span class="custom-radio"></span>
<span class="option-title">$Title</span>
</label>
</li>
<% end_loop %>
</ul>
<% if $Message %><span class="message $MessageType">$Message</span><% end_if %>
<% if $Description %><p class="description">$Description</p><% end_if %>
</div>
> You can tweak class names/markup any time—these are just examples matching your layouts.
## 2) Use per‑field holder templates in PHP
use SilverStripeFormsOptionsetField;
use SilverStripeFormsFieldList;
use SilverStripeFormsForm;
use SilverStripeFormsFormAction;
use SilverStripeFormsRequiredFields;
public function MyForm()
{
$source = [
'option1' => 'option1',
'option2' => 'option2',
'option3' => 'option3',
];
$inline = OptionsetField::create('QualitatInline', 'Qualität (Inline)', $source)
->setFieldHolderTemplate('InlineOptionsetField_holder');
$twoCol = OptionsetField::create('QualitatTwoCol', 'Qualität (Two Columns)', $source)
->setFieldHolderTemplate('TwoColOptionsetField_holder');
$fields = FieldList::create($inline, $twoCol);
$actions = FieldList::create(FormAction::create('doSubmit', 'Save'));
$validator = RequiredFields::create(['QualitatInline', 'QualitatTwoCol']);
return Form::create($this, 'MyForm', $fields, $actions, $validator);
}
## 3) Flush templates
Hit any page with `?flush=all` after adding the `.ss` files.
### Optional (if you also need to change just the inner radios)
Create `InlineOptionsetField.ss` / `TwoColOptionsetField.ss` and call:
$inline->setTemplate('InlineOptionsetField');
$twoCol->setTemplate('TwoColOptionsetField');
(Usually the holder template is enough since it includes label/wrappers.)
That’s it—same `OptionsetField` class, two different layouts per instance.
If you don’t have `app/templates/` yet, you can safely create it.
—
## Where to put your templates
– In a standard **SilverStripe 4+ project** you’ll have a module called `app` (sometimes called `mysite` in older installs).
– Inside that, create a `templates/` folder if it doesn’t exist:
app/
└── templates/
├── InlineOptionsetField_holder.ss
└── TwoColOptionsetField_holder.ss
*(Or `mysite/templates/…` if your base folder is named `mysite`.)*
—
## Rules to remember
– The filename must match what you pass into
`->setFieldHolderTemplate('InlineOptionsetField_holder')`
– The `.ss` file must sit directly under `templates/` or in the correct sub-folder (no PHP namespace folders needed for custom holder templates).
– After adding the files:
**visit any page with `?flush=all`** to clear template cache.
—
## Example recap
$inline = OptionsetField::create('QualitatInline', 'Qualität (Inline)', $source)
->setFieldHolderTemplate('InlineOptionsetField_holder');
Will look for:
app/templates/InlineOptionsetField_holder.ss
—
👉 If you confirm your project root folder name (e.g. `app/`, `mysite/`, or something else), I can tell you the exact folder path. Do you want me to adapt it for your exact folder structure?
Now I have add new style OptionsetFieldList.ss
use SilverStripeFormsOptionsetFieldList include like this
[Emergency] Uncaught Error: Class "SilverStripeFormsOptionsetFieldList" not found
You just need an extra **template file** and then tell your existing `OptionsetField` to use it.
## Do this instead
### 1) Put your alternate template in the theme
Keep your global override where it is:
themes/<yourtheme>/templates/SilverStripe/Forms/OptionsetField.ss (global)
Create a **second, custom template** (no namespace folders for custom names):
themes/<yourtheme>/templates/OptionsetFieldList.ss
(or, if you want to change the holder markup, use `OptionsetFieldList_holder.ss`)
Example `OptionsetFieldList.ss`:
<div class="radio_group">
<label class="form-label">$Title</label>
<div class="d-flex">
<% loop $Options %>
<label class="radio-wrapper">
<input type="radio"
name="$Name"
value="$Value"
id="$ID"
$AttributesHTML
<% if $isChecked %>checked="checked"<% end_if %> />
<span class="custom-radio"></span> $Title
</label>
<% end_loop %>
</div>
<% if $Message %><span class="message $MessageType">$Message</span><% end_if %>
<% if $Description %><p class="description">$Description</p><% end_if %>
</div>
### 2) Select that template per field (no `use` statement)
use SilverStripeFormsOptionsetField;
$alt = OptionsetField::create('QualitatAlt', 'Qualität (List)', $source)
->setTemplate('OptionsetFieldList'); // looks for templates/OptionsetFieldList.ss
If you customized the **holder** instead, do:
$alt = OptionsetField::create('QualitatAlt', 'Qualität (List)', $source)
->setFieldHolderTemplate('OptionsetFieldList_holder');
### 3) Make sure your theme is active and flush
In `app/_config/theme.yml` (or equivalent), your theme should be first:
---
Name: theme
After:
- '#coretheme'
---
SilverStripeViewSSViewer:
themes:
- '<yourtheme>'
- '$default'
Then visit any page with `?flush=all`.
—
**Key points**
– Don’t `use SilverStripeFormsOptionsetFieldList`; it’s not a class.
– Extra layouts = extra `.ss` files. Pick them with `setTemplate()` or `setFieldHolderTemplate()` on each field.
– Put custom‑named templates at `themes//templates/`, not under `SilverStripe/Forms/`, unless you are **overriding** the core template.