Skip to content

Customising views

The package renders Bootstrap 5 markup by default. You can change it at three levels, from a single class to a whole theme of your own.

1. Change classes

Every class the views use comes from the theme in the configuration. Override single classes in the constructor of app/Config/Forms.php:

app/Config/Forms.php
    public bool $showErrorSummary = true;

    public function __construct()
    {
        parent::__construct();

        // Change single classes of the Bootstrap 5 theme.
        $this->themes['bootstrap5']['classes']['submit'] = 'btn btn-success';
        $this->themes['bootstrap5']['classes']['group']  = 'mb-4';

        // A second theme: your own views in app/Views/forms/compact. It
        // extends Bootstrap 5, so templates it lacks come from there.
        $this->themes['compact'] = [
            'views'           => 'forms/compact',
            'extends'         => 'bootstrap5',
            'required_marker' => ' <abbr title="required">*</abbr>',
            'classes'         => array_merge($this->themes['bootstrap5']['classes'], [
                'group' => 'mb-2',
                'input' => 'form-control form-control-sm',
            ]),
        ];
    }

The first two lines change classes for every form: green submit buttons and more space between fields. The class keys are listed in vendor/ephraitech/ci4-forms/src/Config/Forms.php. The rest of the constructor creates a second theme, explained in section 3.

2. Edit the views

To change the HTML itself, copy the views into your app:

php spark forms:publish --config

This creates app/Views/forms/bootstrap5/ with one file per field type, and an app/Config/Forms.php pointing the theme at it. Edit any file there. If you already have a configuration file, the command prints the one line to add.

Running the command again adds files that are missing, for example after an upgrade that brings new field types, and never overwrites the ones you changed. --force replaces them with the package's latest versions.

Views receive prepared variables and two helpers:

Name Contains
$name, $inputName, $id, $label The field's name, its HTML name (tags[] for lists), id and label
$value, $values The value to show, as text and as a list
$error, $help The error message and help text, or null
$attributes Extra attributes, already escaped
$requiredMarker The required marker HTML, or an empty string
$e($text) Escapes text for HTML
$class('group') class="..." with the theme's classes for that part

The full list is documented at the top of each view file.

3. Create a theme

A theme of your own lives in its own folder. With extends, it only needs the templates it changes; the rest come from the theme it extends. The constructor in section 1 registers a compact theme for dense admin screens, which changes only text-like inputs:

app/Views/forms/compact/field_input.php
<?php
/**
 * The compact theme's text-like inputs: label and input on one line.
 * Variables are the same as in the package's field_input view.
 */
?>
<?php if (! $bare): ?>
<div<?= $class('group') ?>>
    <div class="row align-items-center g-2">
        <label for="<?= $e($id) ?>" class="col-sm-4 col-form-label col-form-label-sm"><?= $e($label) ?><?= $requiredMarker ?></label>
        <div class="col-sm-8">
<?php endif ?>
            <input type="<?= $e($inputType) ?>" name="<?= $e($inputName) ?>" id="<?= $e($id) ?>" value="<?= $e($value) ?>"<?= $class('control') ?><?= $attributes ?>>
<?php if (! $bare): ?>
<?php if ($error !== null): ?>
            <div id="<?= $e($errorId) ?>"<?= $class('error') ?>><?= $e($error) ?></div>
<?php endif ?>
        </div>
    </div>
</div>
<?php endif ?>

Select it for every form with public string $theme = 'compact'; in the configuration, or for one form in a controller:

$form->getConfig()->theme = 'compact';

A theme's classes are not inherited, which is why the example starts from the Bootstrap 5 classes with array_merge() and changes two.

Common mistakes

Editing files in vendor/. Changes there are lost on the next composer update. Publish the views instead.

Printing values without $e(). The variables contain what visitors typed. Use $e() for anything you print; only $attributes and $requiredMarker are ready to print.

Expecting published views to update themselves. Published files are yours. After an upgrade, read the changelog for view changes and compare, or publish again with --force and reapply your edits.