ui-awesome / html-field
Form field widget for PHP: renders form controls bound to a form model with label, hint, error, and validation state handling, plus an immutable semantic control factory for application-scoped config recipes.
Requires
- php: ^8.3
- ui-awesome/form-model: ^0.2
- ui-awesome/html: ^0.6
- ui-awesome/html-attribute: ^0.8
- ui-awesome/html-contracts: ^0.2
- ui-awesome/html-core: ^0.8
- ui-awesome/html-helper: ^0.7
- ui-awesome/html-interop: ^0.4
- ui-awesome/html-mixin: ^0.8
Requires (Dev)
- infection/infection: ^0.34
- maglnet/composer-require-checker: ^4.1
- php-forge/baseline: ^0.1
- php-forge/coding-standard: ^0.3
- php-forge/support: ^0.3
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.2
- phpstan/phpstan-strict-rules: ^2.0.3
- phpunit/phpunit: ^12.5
- yii2-extensions/scaffold: ^0.2
This package is auto-updated.
Last update: 2026-07-31 14:43:05 UTC
README
Html Field
A fluent, immutable PHP library for rendering form fields bound to a form model.
Labels, hints, errors, and controls composed through application-scoped configuration.
Features
Installation
composer require ui-awesome/html-field:^0.1
Quick start
Render a field bound to a form model
The field resolves the id, name, and label from the form model and renders a text input by default.
use App\Model\BasicForm; use UIAwesome\Html\Field\Field; echo Field::tag() ->formModel(new BasicForm()) ->property('username') ->render();
Html output:
<div> <label for="basicform-username">Username</label> <input id="basicform-username" name="BasicForm[username]" type="text"> </div>
Hints and validation errors
Hints link to the input through aria-describedby; property errors render after the control.
use App\Model\BasicForm; use UIAwesome\Html\Field\Field; $form = new BasicForm(); $form->addError('username', 'Username is required.'); echo Field::tag() ->formModel($form) ->property('username') ->hintContent('Choose a unique username.') ->render();
Html output:
<div> <label for="basicform-username">Username</label> <input id="basicform-username" name="BasicForm[username]" type="text" aria-describedby="basicform-username-help"> <div id="basicform-username-help"> Choose a unique username. </div> <div> Username is required. </div> </div>
Replace the control and style the container
Any form control can replace the default input; the form model field config is applied to the replacement.
use App\Model\BasicForm; use UIAwesome\Html\Field\Field; use UIAwesome\Html\Form\InputEmail; echo Field::tag() ->formModel(new BasicForm()) ->property('username') ->input(InputEmail::tag()) ->containerClass('form-group') ->render();
Html output:
<div class="form-group"> <label for="basicform-username">Username</label> <input id="basicform-username" name="BasicForm[username]" type="email"> </div>
Semantic control factory
Field selects controls through ControlFactory and applies application-scoped recipes to the field, container,
control-specific input container and label, control, hint, error, prefix, and suffix contexts. The package does not
select a theme: replace $theme with any ThemeInterface implementation, such as Bootstrap5Theme or TailwindTheme.
use UIAwesome\Html\Core\Config\Config; use UIAwesome\Html\Field\Factory\ControlFactory; use UIAwesome\Html\Field\Field; $config = new Config(theme: $theme, factory: new ControlFactory()); echo Field::tag() ->config($config) ->control('email') ->formModel($form) ->property('email') ->render();
The default registry supports checkbox, checkbox-list, email, password, radio, radio-list, select,
text, and textarea. Registrations are immutable — derive a factory with with() to replace or extend them.
Select and its typed Option objects come from ui-awesome/html: compose the control there and the field passes
the resolved model value to Select::value().
CheckboxList, RadioList, and ChoiceItem also come from ui-awesome/html; Field supplies their checked values,
name, validation state, label, hint, and errors. See the usage guide for examples, slot contexts, and recipe methods.
Strict field configurations
Form model field configurations are applied through the core config applier in strict mode, once per render, against
the control the field finally resolves — so the fluent call order never changes the outcome. An entry naming a method
the resolved control does not expose throws ConfigException instead of being skipped, so typos such as maxlenght
fail at render time. The model binding runs first and the config last, so entries such as value, id, name,
checked, and placeholder act as explicit per-property overrides rather than being silently overwritten. See the
upgrade guide for the precedence rules and supported entry shapes.
Documentation
For detailed usage, testing, and quality workflows.