Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Html Laravel Package

laravellux/html

LaravelLux HTML is a Laravel package for building HTML through a fluent, composable API. It provides helpers for elements, attributes, forms, and Blade-friendly rendering, helping keep views clean, reusable, and easy to maintain.

Deep Wiki
Context7

Getting Started

The package re-establishes the classic Form and Html builders for Laravel — the same API the abandoned laravelcollective/html provided. Treat it as a drop-in replacement for hand-written <form> boilerplate: CSRF tokens, method spoofing, old() repopulation, and model-backed inputs.

  1. Install and confirm discovery.

    composer require laravellux/html
    

    Laravel's package auto-discovery should register the service provider and the Form / Html aliases. If Form::open() throws "Class 'Form' not found," add them manually in config/app.php:

    'aliases' => [
        'Form' => Laravellux\Html\FormFacade::class,
        'Html' => Laravellux\Html\HtmlFacade::class,
    ],
    

    Verify the exact namespaces in the package's composer.json / src/ before assuming — the repository details are not published.

  2. Publish the config (optional but recommended early).

    php artisan vendor:publish --tag=html
    

    This gives you the default form/select classes, label_format, and error_bag. Without it you're running on package defaults, which is fine but harder to reason about when markup surprises you.

  3. First real use case — replace a manual create form.

    {!! Form::open(['route' => 'posts.store', 'files' => true]) !!}
        {!! Form::label('title', 'Title') !!}
        {!! Form::text('title') !!}
        {!! Form::submit('Save') !!}
    {!! Form::close() !!}
    

    Compare against what you wrote before: no @csrf, no old('title'), no enctype, no manual value= attribute. That delta is the entire value proposition — everything else is variations on it.

Where to look first: the README for the facade method list, then src/FormBuilder.php for the exact escaping and old()-resolution behaviour. Because this is a low-star, single-maintainer package, read the source for anything you're relying on in production rather than assuming parity with laravelcollective.

Implementation Patterns

Model binding for edit forms. This is the pattern you'll use most:

{!! Form::model($post, ['route' => ['posts.update', $post], 'method' => 'PUT']) !!}
    {!! Form::text('title') !!}
    {!! Form::textarea('body') !!}
    {!! Form::select('status', $statuses) !!}
{!! Form::close() !!}

Form::model() seeds every field from the model, with old() taking precedence after a validation failure. Form::close() resets that context — always pair them.

Action-based vs. route-based opening. Prefer 'route' => [...] or 'action' => [...] over a raw 'url'; you get URL generation and correct method spoofing in one array. Add 'files' => true whenever any input is type="file".

Validation-failure round trip. The builder reads from the flashed input automatically. Keep your error display standard:

@error('title') <span class="text-red-600">{{ $message }}</span> @enderror

If you validate with a named bag ($request->validateWithBag('login', ...)), pass 'error_bag' => 'login' to Form::open() so the builder highlights the right fields, or set it globally in config.

Custom field components. Don't sprinkle Form:: calls across fifty views. Wrap them:

{{-- resources/views/components/field.blade.php --}}
<div>
    {!! Form::label($name, $label) !!}
    {!! Form::$type($name, $value, $attributes) !!}
    @error($name) <p>{{ $message }}</p> @enderror
</div>

Call via <x-field name="title" type="text" label="Title" />. This keeps the builder's old()/model logic while giving you one place to change markup.

Macros for domain-specific inputs. Register once in a service provider's boot():

Form::macro('money', function ($name, $value = null) {
    return Form::number($name, $value, ['step' => '0.01', 'min' => 0]);
});

Then Form::money('price') works everywhere. The same mechanism exists on Html::macro() for things like Html::cdnScript($path).

Collection-backed selects. Always reduce to a key/value shape:

{!! Form::select('author_id', $authors->pluck('name', 'id'), null, ['placeholder' => 'Choose…']) !!}

Passing Eloquent models directly to Form::select is a common source of __toString errors or [object Object]-style labels.

Escaping and layout. For anything the builder doesn't own — wrappers, grid classes, error summaries — stay in Blade. The builders are for inputs and forms, not page structure. Use Html::script() / Html::style() only if you're not on Vite; if you are, they add nothing.

Testing. The output is deterministic HTML, so assertSee('name="title"', false) and route-based action="..." assertions are cheap regression tests. Assert the _token field exists in one feature test per form to catch a broken provider registration early.

Gotchas and Tips

  • {!! !!}, not {{ }}. The builders return HTML strings. Blade's escaped echo will render <input ...> as literal text. This is the single most common mistake and it looks like a broken package rather than a broken template.
  • Form::model() leaks state. If you open a model form and forget Form::close(), the next plain Form::open() inherits the model and prefills unexpectedly. close() is not cosmetic.
  • old() beats the model. On a failed update, fields show the submitted (invalid) value, not the database value — that's correct behaviour, but it confuses people debugging "stale" form data. Check the session's _old_input before assuming a bug.
  • Checkboxes never send a false value. Form::checkbox('tos', 1) on an existing model is checked when the model attribute is truthy, but an unchecked box sends nothing. For boolean updates, add Form::hidden('tos', 0) before the checkbox or validate with sometimes|boolean.
  • Array inputs and error keys diverge. Form::text('address[city]') produces name="address[city]", but validation errors are keyed address.city. Your @error('address.city') must use dot notation while the input name uses brackets.
  • Select option values are keys, labels are escaped. If you need rich labels (icons, badges), build the <option> markup yourself or accept plain text. Passing HTML through labels renders it literally.
  • CSRF and _method are injected for you. Don't hand-add @csrf inside a Form::open() — you'll send two _token fields. If you're getting TokenMismatchException, the likely cause is a partial rendered outside the builder (e.g. an AJAX-replaced fragment) or a form rendered before the session started.
  • Config defaults are invisible until published. Unexpected class="form-control" or class="form-group" attributes come from the package config. Publish it and set default_form_class / default_select_class to match your CSS framework instead of overriding per-call.
  • Octane and macros. Macros are registered on a static facade root and persist across requests under Octane. Never capture $request or auth()->user() inside a macro closure at boot time — resolve them inside the closure body on each call.
  • Conflicts on the Form / Html aliases. Do not install this alongside laravelcollective/html or another builder. If Form::open() resolves to an unexpected class, inspect config/app.php aliases and the extra.laravel.aliases entry in composer.json — later packages silently win.
  • Extension point for deep changes. Macros cover most needs. For structural changes (custom attribute rendering, different escaping), extend the package's FormBuilder and rebind it in a service provider rather than editing vendor files. Confirm the binding key by reading the package's provider.
  • Pin the version and keep an exit plan. With 36 stars and an unreleased repository reference, treat this as a maintained fork you may have to fork again. The API mirrors laravelcollective, so migrating back to raw Blade (@csrf, old(), @method) or to spatie/laravel-html is mechanical — keep the Form:: calls concentrated in your components so that swap touches a handful of files, not every view.
  • Verify Laravel version support. Check the illuminate/support constraint in the package's composer.json against your app before adopting; recent release dates imply current Laravel, not universal compatibility.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource