Create form field SilverStripe

User
HOw to create new form field

$Title

in silver stripe cms

Assistant
Got you. In SilverStripe you don’t “echo inputs” directly—you define a field in PHP, then (optionally) give it a custom template. Your HTML snippet matches the variables exposed by `OptionsetField`, so the cleanest way is to use an `OptionsetField` and override its template.

### 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.

User
what if I want to use two different layout form OPtion field

$Title

$Title

Assistant
You can have **two different layouts** for the same `OptionsetField` by giving each field its **own template**. Because your second snippet includes the label and wrapper, you should override the **holder template** (and optionally the inner field template).

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.

User
I want this
Option B — Same class, choose templates per instance
Assistant
Great — here’s the **exact setup for Option B**.

## 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.

User
we have no folder app/template
Assistant
Right 👍 — in SilverStripe the **template lookup paths** are based on your project structure.
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?

User
Actually we have created a file themes/template/templates/SilverStripe/Forms/OptionsetField.ss
Now I have add new style OptionsetFieldList.ss
use SilverStripeFormsOptionsetFieldList include like this
[Emergency] Uncaught Error: Class "SilverStripeFormsOptionsetFieldList" not found
Assistant
You don’t need (and shouldn’t create) a PHP class called `OptionsetFieldList`. That’s why `use SilverStripeFormsOptionsetFieldList` crashes—there’s no such class.

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.

Leave a Comment

Your email address will not be published. Required fields are marked *