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

Bs Select Bundle Laravel Package

axiolab/bs-select-bundle

A Symfony bundle that integrates Bootstrap Select into your forms, adding a ready-made form type and Twig rendering for searchable, styled dropdowns with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

First, a reality check. This is a Symfony bundle, not a Laravel package. It has no service provider, no config/bs-select.php, and nothing that registers with Laravel's container. It works by hooking Symfony's Form component — overriding the choice widget renderer so a ChoiceType/EntityType emits the markup and assets that bootstrap-select expects. There is no composer require path from a Laravel app to a working select. The value here is the pattern, not the code.

Two paths, pick one up front:

  1. You're actually on Symfony (or maintaining a legacy Symfony app) — install it, but verify compatibility first. The repo predates Symfony Flex conventions; expect manual bundle registration in config/bundles.php and a form_themes entry pointing at the bundle's Twig namespace.
  2. You're on Laravel (the likely case) — port the idea in ~30 lines. You are re-implementing a form theme override plus an asset include. That's a Blade component and a small JS initializer.

Where to look first in the repo, in this order:

  • README.md — for the intended type name and asset setup. Given zero stars and zero dependents, assume it's thin or stale.
  • Resources/views/Form/ — the form theme. This is the whole trick: it overrides choice_widget / choice_widget_collapsed to add class="selectpicker" and data-* attributes.
  • Form/Type/ — the custom type that presumably extends ChoiceType.
  • Resources/public/ or composer.json — whether bootstrap-select itself is vendored, or you're expected to provide it.
  • Check the last commit date and the symfony/* constraints in composer.json before investing anything.

First use case, either path: a single <select> with 100+ options (countries, categories, users) that needs typeahead, a "select all" action, and multi-select — which native <select multiple> handles poorly. Bootstrap-select solves exactly that and nothing more.

In Laravel, the minimal port:

{{-- resources/views/components/bs-select.blade.php --}}
@props(['name', 'options' => [], 'selected' => null, 'multiple' => false, 'search' => true])

<select
    name="{{ $name }}{{ $multiple ? '[]' : '' }}"
    @if($multiple) multiple @endif
    {{ $attributes->merge(['class' => 'form-select selectpicker']) }}
    @if($search) data-live-search="true" @endif
>
    @foreach($options as $value => $label)
        <option value="{{ $value }}"
            @selected(in_array((string) $value, array_map('strval', Arr::wrap(old($name, $selected ?? [])))))>
            {{ $label }}
        </option>
    @endforeach
</select>

Then one initializer, run once:

// resources/js/bs-select.js
import 'bootstrap-select/dist/css/bootstrap-select.min.css';
import 'bootstrap-select';

const init = (root = document) =>
  root.querySelectorAll('.selectpicker:not(.initialized)')
      .forEach(el => window.jQuery(el).selectpicker().addClass('initialized'));

document.addEventListener('DOMContentLoaded', () => init());

Implementation Patterns

The three patterns the bundle exposes (and what they map to in Laravel):

  1. Custom form type. Use the bundle's type instead of ChoiceType — typically something in the axiolab\BsSelectBundle\Form\Type namespace. This is the cleanest entry point if it exists, because it carries the attr defaults for you. In Laravel the analogue is the Blade component above: a named, reusable widget rather than sprinkling class="selectpicker" across views.

  2. Global form theme vs. per-form theme. Symfony lets you register a theme globally (twig.form_themes) or scope it with {% form_theme form 'BsSelectBundle:Form:bs_select.html.twig' %}. Prefer the scoped version while evaluating an unmaintained bundle — a broken theme override applied globally will mangle every form in the app. In Laravel, scope is implicit: only views that use <x-bs-select> are affected. That's a genuine advantage of the port.

  3. Attribute-driven configuration. Almost all behavior is data-* on the select: data-live-search="true", data-actions-box="true" (select all / deselect all), data-selected-text-format="count > 3", data-width="100%", data-size="10". If the bundle's type doesn't expose these as options, pass them through attr. Do this in attr, not in the theme — data-* in a form theme is where maintenance pain lives.

Day-to-day workflow that actually holds up:

  • Long static lists (countries, currencies, enum-ish lookups): component + data-live-search. Straightforward, no server involvement.
  • BelongsToMany / multi-select relations: multiple => true plus data-actions-box="true". Name the field roles[]; validate with 'roles' => ['array'], 'roles.*' => ['exists:roles,id']. The transform is purely client-side, so the underlying <select multiple> still posts an array — nothing changes in your FormRequest.
  • Selected state after validation failure: this is where naive integrations break. Because bootstrap-select renders a copy of the select's state into the DOM, old() must be applied at render time (as in the component above) and the plugin must be initialized after the DOM reflects it. Order matters: render → init, never init → render.
  • Dynamic options (AJAX/typeahead against a large table): bootstrap-select does not do remote loading. Don't force it. If you need server-side search, use Select2 or Choices.js instead — they're built for it. Keep bootstrap-select for lists you can afford to render server-side.
  • Livewire / Inertia / Turbo: the plugin initializes once and then goes stale. Re-init in a hook / onload / Turbo turbo:load handler, and call .selectpicker('refresh') after any option list mutation. This is the single most common source of "it works on first load, then stops."

Integration tips:

  • Asset order is non-negotiable: jQuery → Bootstrap (if you're relying on its styles) → bootstrap-select → your initializer. With Vite, put the first three in the same entry chunk; do not rely on @vite ordering across separate tags.
  • Keep the initializer idempotent (the :not(.initialized) guard) so partial re-renders don't double-wrap.
  • If you're on Symfony and the bundle vendors bootstrap-select, check whether the version is 1.13 (BS3-era) or 1.14 (BS4/BS5). They differ in markup and CSS variables and will fight your theme.

Gotchas and Tips

Signal quality. Zero stars, zero dependents, empty description grammar. Treat this as a reference implementation to read, not a dependency to install. There is no community, no Stack Overflow corpus, no issue triage. Pin an exact version if you vendor it, and be prepared to fork. Before anything else, check the last commit date and whether the symfony/form constraint allows your version — a bundle that overrides choice_widget is tightly coupled to the theme block names, which changed between Bootstrap 3/4/5 layouts.

Double-styling with Symfony's own Bootstrap form themes. If you already use bootstrap_4_layout.html.twig or bootstrap_5_layout.html.twig, those already style selects. Layering bootstrap-select on top produces a styled <select> and a styled replacement button. Register the bundle theme with higher priority, or explicitly disable the conflicting blocks — don't assume the bundle wins.

$(...).selectpicker is not a function means the plugin script never executed. Causes, in order of likelihood: jQuery loaded twice (a second copy scoped to a module), bootstrap-select loaded before jQuery, or the script was tree-shaken out of the Vite build because it was only imported for side effects without a CSS/import reference. Check window.jQuery.fn.selectpicker in the console.

selectpicker('refresh') is mandatory, not optional. Any time you change options, toggle disabled, or re-render a Livewire component, the visible widget is stale until you refresh. Wire it into a single helper and call it from one place; scattered calls rot fast.

Native select is still the source of truth — good. Since the plugin hides, but does not remove, the <select>, server-side validation, old(), and $request->validate() all work unchanged. Don't be tempted to validate against whatever the plugin's DOM shows.

Accessibility regression. bootstrap-select replaces the control with a <button> plus generated divs. Screen-reader semantics are weaker than a native <select>, and keyboard navigation has known quirks (particularly inside modals where Bootstrap traps focus). If your app has an accessibility requirement, this is a reason to prefer a native select with <datalist> or a plain search input, or to pick a plugin with better a11y support.

Modals and dropdown clipping. A select inside a Bootstrap modal will have its menu clipped by overflow: hidden on the modal body. Set data-container="body" on the select, and expect z-index fights with the modal backdrop.

Extension points worth knowing if you stay on Symfony: override the choice_widget_collapsed block rather than choice_widget, so expanded => true (radio/checkbox) forms keep rendering normally. A FormTypeExtension is usually cleaner than a custom type — it lets ChoiceType itself gain the behavior instead of forcing call sites to remember a different class name. In Laravel, the equivalent lever is a Blade component class plus a @once @push('scripts') for the initializer, keeping the per-view footprint to one tag.

Debugging recipe. View source, not devtools-inspect: confirm the <select> actually carries selectpicker and your data-* attributes. If they're absent, the theme/component never applied — on Symfony run bin/console debug:twig | grep -i select, on Laravel check that the component is resolved from the right namespace. If the attributes are present but nothing renders, it's a JS problem, not a template problem. Those are separate failure modes; diagnose them separately.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle