K

Forms

Html

Raw markup inside a schema, and the static helpers that build the common pieces of it.

On this page

Markup dropped straight into the schema. Reach for Html when a form needs something that is not a field and not a sentence — a rule between two groups, a heading the layout components do not give you, a block of your own markup. For a value with a label above it use Placeholder; for a whole partial use ViewField.

use NyonCode\WireForms\Components\Display\Html;

How It Works

Html is a display component: it renders output and never binds to form state. No state path, no validation, nothing submitted.

Its content is rendered unescaped, always. There is no escape() switch here — unlike Placeholder, which escapes by default, and ViewField, which lets you choose. What you set is what reaches the page:

Html::make()->content($userSuppliedString) // never do this

Anything with user input in it must be sanitised before it gets here, or belong in a component that escapes.

The name is optional, which is unusual — Html::make() with no argument generates html_<uniqid> for itself, because a component that holds no state has nothing to be addressed by. Pass a name only if you want one for your own reference.

The static factories are the safe path. divider(), spacer(), heading() and paragraph() do not concatenate strings: each sets content() to a closure that renders a Blade partial, and the partial escapes the text with {{ }}. So Html::heading($fromTheDatabase) is safe in a way Html::make()->content(...) is not.

Two consequences of it being a closure rather than a rendered string: the markup is only built for a component that is actually shown, and the partials — wire-forms::components.html.* — are the publish-and-override point, like every other view this package ships.

heading() picks its own type scale from the level: 1 is text-2xl font-bold, 2 (the default) text-xl font-semibold, 3 text-lg font-medium, and anything else text-base font-medium. The level decides the tag as well, so heading('Billing', 3) is an <h3>.

Basic Usage

Html::make()
->content('<div class="rounded bg-gray-50 p-3 text-sm">Anything you like.</div>')

The Static Helpers

Html::divider(); // <hr> with vertical margin
Html::spacer('8'); // an empty div, Tailwind height step
Html::heading('Billing details'); // <h2>, the default level
Html::heading('Card', 3); // <h3>
Html::paragraph('We never store card numbers.');

These are the ones to reach for by default: they escape their text, and their markup is one published partial rather than a string in your schema.

Breaking A Long Form Up

Html::heading('Contact'),
TextInput::make('email')->email(),
TextInput::make('phone'),
 
Html::divider(),
 
Html::heading('Billing'),
TextInput::make('vat_number'),

A Section does this with a card, a fold and header actions; Html::heading() plus Html::divider() is the flat version, for a form that wants the rhythm without the boxes.

Extended Example

A settings form in a real Livewire host, using the factories for structure and one raw block for something the framework does not ship:

use Livewire\Component;
use NyonCode\WireForms\Components\Display\Html;
use NyonCode\WireForms\Components\TextInput;
use NyonCode\WireForms\Components\Toggle;
use NyonCode\WireForms\Forms\Form;
use NyonCode\WireForms\Forms\WithForms;
 
class WorkspaceSettings extends Component
{
use WithForms;
 
public ?array $data = [];
 
public function form(Form $form): Form
{
return $form
->statePath('data')
->model(Workspace::class)
->schema([
Html::heading('General'),
Html::paragraph('Everyone in the workspace sees these.'),
 
TextInput::make('name')->required(),
TextInput::make('slug')->required(),
 
Html::divider(),
 
Html::heading('Danger zone', 3),
Html::make()->content(
'<p class="text-sm text-red-600">Deleting a workspace cannot be undone.</p>'
),
 
Toggle::make('scheduled_for_deletion')
->label('Schedule this workspace for deletion'),
])
->successMessage('Settings saved');
}
 
public function save(): void
{
$this->form->save();
}
}

The headings and the paragraph carry text the factories escape; the one raw block is a literal the developer wrote, which is the only kind of string that belongs in content().

Html API

->content(string|Closure|null $content) // rendered UNESCAPED — see How It Works
->getContent(): ?string
Html::make(?string $name = null): static // the name is optional
Html::divider(): static // an <hr>
Html::spacer(string $size = '4'): static // an empty div at a Tailwind height step
Html::heading(string $text, int $level = 2) // <h1>–<h3>, escaped, with a matching type scale
Html::paragraph(string $text): static // a <p>, escaped

Visibility and columnSpan() are the shared component surface — see Common Field API. Validation, live() and defaults do not apply: Html holds no state.

  • Placeholder — text with a label, escaped by default
  • ViewField — a whole Blade partial instead of a string
  • Alert — a coloured box for a message
  • Section — headings with a card around them