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

Bootstrap Form Laravel Package

watson/bootstrap-form

watson/bootstrap-form is a Laravel package that adds Bootstrap-friendly form builder helpers for labels, inputs, errors, and validation states, making it easier to build clean, accessible forms with less repetitive markup.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package alongside the Laravel form builder it extends (the dependency changes across releases — check the tag you install):

composer require watson/bootstrap-form

Register the provider and facade in config/app.php (this package predates auto-discovery, so this manual step is required):

'providers' => [
    // ...
    Watson\BootstrapForm\BootstrapFormServiceProvider::class,
],

'aliases' => [
    'BootstrapForm' => Watson\BootstrapForm\Facades\BootstrapForm::class,
],

Publish the config so you can see what is actually being generated:

php artisan vendor:publish --provider="Watson\BootstrapForm\BootstrapFormServiceProvider"

Open config/bootstrap-form.php first — this is the source of truth for the wrapper classes (form-group, form-control, control-label, has-error, help-block), and it is where you confirm the option keys the builder accepts in your version.

First use case — a create form. Use the package facade rather than Form:: so you always hit the Bootstrap-aware builder:

{!! BootstrapForm::open(['route' => 'users.store']) !!}

    {!! BootstrapForm::text('name') !!}
    {!! BootstrapForm::email('email') !!}
    {!! BootstrapForm::password('password') !!}

    {!! BootstrapForm::submit('Create user', ['class' => 'btn btn-primary']) !!}

{!! BootstrapForm::close() !!}

Each call returns a complete form-group with <label>, the control, and (when validation fails) a help-block error span. open() handles CSRF and method spoofing for you.

Implementation Patterns

Model binding for edit forms. Use model() so values and selected/checked states come from the model, and spoof the verb for updates:

{!! BootstrapForm::model($user, ['route' => ['users.update', $user], 'method' => 'PUT']) !!}
    {!! BootstrapForm::text('name') !!}
    {!! BootstrapForm::select('role_id', $roles) !!}
    {!! BootstrapForm::textarea('bio') !!}
    {!! BootstrapForm::submit('Save changes', ['class' => 'btn btn-primary']) !!}
{!! BootstrapForm::close() !!}

Share one partial between create and edit. Because the builder returns a string, the same partial works for both: start the form in the view, include the fields partial, close the form. Keep the submit button out of the partial if labels differ.

Selects with a placeholder. Merge an empty key into the options array:

{!! BootstrapForm::select('role_id', ['' => 'Choose a role'] + $roles->pluck('name', 'id')->all()) !!}

Checkboxes and radios take Laravel's signature (name, value, checked, options), so the checked flag has to be passed explicitly:

{!! BootstrapForm::checkbox('terms', 1, old('terms', false), ['label' => 'I accept the terms']) !!}
{!! BootstrapForm::radio('plan', 'monthly', true, ['label' => 'Monthly']) !!}
{!! BootstrapForm::radio('plan', 'yearly', false, ['label' => 'Yearly']) !!}

File uploads need files => true on the opening tag; the field itself is just BootstrapForm::file('avatar').

Validation display is automatic via $errors. The builder reads the shared $errors ViewErrorBag and adds the configured error class plus the message. In Laravel 5.5+ this is shared for you; on 5.0–5.4 ensure ShareErrorsFromSession runs in the relevant middleware group. Controllers then just use $this->validate() or a FormRequest.

Old input. The builder routes values through old($name, $value) for standard inputs, so failed validation repopulates automatically — as long as you redirect back with input (Laravel's validate() does this).

Extension points for anything it does not cover. Register macros on the builder (in a service provider's boot) for custom controls, or subclass the builder and rebind it in the container if you need to change how a whole field type is rendered:

BootstrapForm::macro('currency', function ($name, $value = null, $options = []) {
    return BootstrapForm::text($name, $value, array_merge(['class' => 'form-control text-right'], $options));
});

Layout overrides. For horizontal/BS3 .form-horizontal layouts, either edit the published config classes globally or pass per-field options (class, label, and — depending on version — help) so individual fields deviate from the defaults without forking the package.

Gotchas and Tips

  • The repository is archived. Pin versions deliberately; the package targets Bootstrap 3 markup and older Laravel. On modern Laravel, budget time for a replacement (Blade components, or Laravel Collective plus hand-written wrappers) rather than forcing compatibility.
  • Bootstrap 3 class names are hard-coded by default. BS4/BS5 expect is-invalid / invalid-feedback, not has-error / help-block. Override via config/bootstrap-form.php, but verify the builder does not also emit BS3-only markup in the label/control wrapper.
  • Missing $errors fails silently. If no error bag is shared, the form looks fine but shows no messages. Dump {{ $errors }} (or dd($errors) from the view) before hunting through the package.
  • Array field names break error lookup. Names like addresses[0][city] are looked up verbatim; the builder will not resolve the dotted/bracketed error key unless your version normalises it. Use flat names, or render that field manually and call $errors->first('addresses.0.city') yourself.
  • Checkbox "checked" is not always inferred. Model binding may not mark a checkbox/radio for you. Pass the third argument explicitly, and remember unchecked checkboxes submit nothing — validate with boolean / accepted.
  • Password fields never repopulate. old() is intentionally skipped (or ineffective) for password inputs; do not assume a stale-password bug.
  • File inputs cannot be repopulated. Validate and redirect is all you can do; display the current filename beside the field manually.
  • Config caching masks edits. After publishing or tweaking classes, run php artisan config:clear (or config:cache) — otherwise the old form-group/control-label values stick around and look like a package bug.
  • Check which facade actually binds the builder. Depending on version the provider may rebind form, making plain Form::text() Bootstrap-aware; the BootstrapForm alias is the safer, explicit choice. Confirm by inspecting the provider's register().
  • Debugging rendered HTML. Since every call returns a string, {{ BootstrapForm::text('name') }} (escaped) shows you the generated markup and the options actually applied — much faster than reading the source.
  • Option keys differ by version. Keys such as label and help are not consistent across releases; treat the published config and the package's builder class as authoritative instead of relying on a blog post from the Laravel 4 era.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource