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

Laravel Bootstrap 4 Forms Laravel Package

netojose/laravel-bootstrap-4-forms

Laravel Bootstrap 4 Forms offers an elegant form builder for generating Bootstrap 4-styled forms in Laravel. It handles model binding, validation errors, old input, and common field types, cutting boilerplate markup while keeping your Blade views clean and readable.

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer:

composer require netojose/laravel-bootstrap-4-forms

On Laravel 5.5+ the service provider and Form facade are auto-discovered. On older versions add to config/app.php:

Netojose\LaravelBootstrap4Forms\LaravelBootstrap4FormsServiceProvider::class,
// aliases
'Form' => Netojose\LaravelBootstrap4Forms\Facades\Form::class,

Make sure your layout actually loads Bootstrap 4 CSS/JS — the package only emits markup with BS4 classes, it does not ship assets. Publish the config if you want to tweak wrapper/error classes:

php artisan vendor:publish --provider="Netojose\LaravelBootstrap4Forms\LaravelBootstrap4FormsServiceProvider"

Where to look first

  1. config/laravel-bootstrap-4-forms.php — the class strings applied to form groups, inputs, error states. This is your main customization lever.
  2. src/Form.php (and any FormBuilder/view files) — the full list of available methods and their signatures. The README covers the common ones; the source is the source of truth for the rest.
  3. resources/views/ — the Blade partials that render each control. Publish/override these if you need different markup.

First use case — a simple create form:

{!! Form::open(['url' => route('posts.store'), 'method' => 'POST']) !!}
    {!! Form::text('title', 'Title') !!}
    {!! Form::textarea('body', 'Body', ['rows' => 5]) !!}
    {!! Form::select('status', 'Status', ['draft' => 'Draft', 'published' => 'Published']) !!}
    {!! Form::submit('Save') !!}
{!! Form::close() !!}

open() emits the CSRF token and method spoofing automatically, so most teams start by swapping hand-written <div class="form-group">…</div> blocks for these calls one form at a time.

Implementation Patterns

Model binding for edit forms. Rather than manually computing old()/model-value fallbacks per field, pass the model into open():

{!! Form::open(['model' => $post, 'url' => route('posts.update', $post), 'method' => 'PATCH']) !!}
    {!! Form::text('title', 'Title') !!}
    {!! Form::textarea('body', 'Body') !!}
{!! Form::close() !!}

The package resolves each field's value from old('field') first, then the bound model attribute. This is the single biggest time-saver — it removes the old('title', $post->title ?? '') boilerplate from every input and keeps create/edit partials identical.

Validation feedback comes for free. Because the package reads the shared $errors bag (populated by ShareErrorsFromSession in the web middleware group), a failed FormRequest validation automatically adds is-invalid to the control and renders an invalid-feedback block. You get the Bootstrap 4 error styling without touching your Blade.

One partial for create and edit. Combine model binding with a shared _form.blade.php:

{{-- posts/_form.blade.php --}}
{!! Form::text('title', 'Title', ['required' => true]) !!}
{!! Form::select('status', 'Status', $statuses) !!}

Then create.blade.php and edit.blade.php differ only in the open() call. This is the pattern most teams settle on.

File uploads. Add 'files' => true to the open() options so the enctype is set for you:

{!! Form::open(['url' => route('media.store'), 'files' => true]) !!}
    {!! Form::file('image', 'Image') !!}
    {!! Form::submit('Upload') !!}
{!! Form::close() !!}

Checkbox/radio for boolean and enum fields. Checkboxes take a value and a checked state; radios take an options map plus the selected key. Bind them through the model so "was it checked?" is derived from the record:

{!! Form::checkbox('is_published', 'Published', 1) !!}
{!! Form::radio('visibility', 'Visibility', ['public' => 'Public', 'private' => 'Private']) !!}

Attribute passthrough for everything else. The final array on each helper is passed straight to the underlying input, so placeholder, required, autocomplete, id, data-* and custom classes all work. For bespoke layout you can still hand-write the surrounding markup and only use the helpers for the control itself.

Composition in larger forms. For long forms, extract repeated field groups (address blocks, line items) into partials that take a $prefix/$index and call the helpers with prefixed names. Because the helpers are plain static calls, they compose fine inside Blade @foreach/@include.

Gotchas and Tips

  • Use {!! !!}, not {{ }}. The helpers return HTML strings; escaping them with {{ }} prints markup as text. Only label/value content you pass in is escaped by the package — never concatenate raw user input into a label expecting safety.
  • Laravel Collective name clash. If you also install laravelcollective/html, both register a Form alias. Alias this one differently (e.g. BsForm) or import the full namespace in the file you use it in.
  • Bootstrap 5 will not look right. The markup is BS4-specific: form-group, custom-select, custom-control custom-checkbox, invalid-feedback inside a form-group. On BS5 these no longer map to the same styling. Either stay on BS4 or publish and rewrite the package's views/config to emit mb-3, form-select, form-check, etc.
  • The package is unmaintained (last release Jan 2021). Its composer.json constraints may prevent installation on Laravel 9/10/11. Check before committing to it in a new project; if you must use it, fork and relax the constraints, or vendor the Form class into your app. For a 2024+ codebase, native Blade components or a maintained alternative are the safer bet.
  • old() beats the model. Binding a model does not override a flashed old value — which is what you want, but it surprises people debugging "why isn't it showing the DB value?" after a failed submit.
  • File inputs cannot be repopulated. Browsers forbid setting a file input's value; the package can't restore a selection after a validation failure. Show the existing filename next to the input and let the user re-pick.
  • Checkbox "unchecked" is tricky. An unchecked box sends nothing, so old('is_published') is null and the model's 0/false should be relied on. Make sure your checkbox value and the model cast agree (boolean cast on the model avoids "0" vs false confusion).
  • Multi-select needs array names. For select with multiple, name the field roles[]; otherwise only the last selection is submitted.
  • Debugging rendering issues. Dump the raw output ({{ dd(Form::text('foo', 'Foo')) }}) to see exactly which classes are emitted, then compare with the config. If validation styling isn't appearing, confirm the request goes through the web middleware group (so $errors is shared) and that you're rendering the form after a redirect-back, not in an API route.
  • Customize via config first, views second. Class overrides live in the config file; structural changes require publishing and editing the Blade partials. Prefer the config so upgrades (such as they are) stay simple.
  • Testing. Output is plain HTML, so $response->assertSee('name="title"', false) and assertSee('is-invalid', false) in feature tests cover most of what you need. Assert on attribute presence rather than exact class strings, which are easy to reformat.
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