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

Fontawesome Iconpicker Laravel Package

itsjavi/fontawesome-iconpicker

A lightweight jQuery plugin that adds a searchable Font Awesome icon picker to text inputs. Browse, filter, and select icons from a clean popover UI, with support for multiple Font Awesome versions, keyboard navigation, and easy setup in any web form or admin panel.

Deep Wiki
Context7

Getting Started

This is not a Laravel package — it's a jQuery/Bootstrap frontend widget published on npm as fontawesome-iconpicker. Treat it as an asset with a Blade wrapper, and keep all icon logic on the frontend.

1. Install the assets

npm install fontawesome-iconpicker jquery bootstrap

2. Load order matters (jQuery → Bootstrap → picker). In resources/js/app.js:

import $ from 'jquery';
window.$ = window.jQuery = $;   // required: the plugin registers itself on the global jQuery

import 'bootstrap';
import 'fontawesome-iconpicker';
import 'fontawesome-iconpicker/dist/css/fontawesome-iconpicker.min.css';

If you're on Vite, also double-check optimizeDeps/build.rollupOptions aren't duplicating jQuery — two jQuery instances is the #1 "plugin is not a function" cause.

3. Minimum viable field

{{-- resources/views/components/icon-field.blade.php --}}
@props(['name', 'value' => null])

<div class="input-group">
    <span class="input-group-text"><i id="{{ $name }}-preview" class="{{ $value }}"></i></span>
    <input type="text"
           name="{{ $name }}"
           id="{{ $name }}"
           class="form-control iconpicker"
           value="{{ $value }}"
           data-selected="{{ $value }}"
           autocomplete="off">
</div>
$('.iconpicker').iconpicker({
    title: 'Choose an icon',
    selected: $(this).data('selected') || '',
    placement: 'bottom',
    search: true,
});

4. First real use case — a menus or categories table with an icon column you render in a sidebar. Add $table->string('icon')->nullable() and output it as <i class="{{ $item->icon }}"></i>. That's the sweet spot for this library: an admin CRUD form where a human picks a class string.

Where to look first: the dist/ folder for the built CSS/JS, and the demo page's option list. Skip the source unless you need to fork it (you may — see Gotchas).

Implementation Patterns

Make it a Blade component, not inline markup. Every CRUD form ends up with the same input group; centralise it as x-icon-field and pass the current value in. Keep a <i> preview next to the input and update it in the iconpickerSelected handler.

Store the raw class string, render defensively. The picker emits a fa fa-* (Font Awesome 4-era) string. Store that string in one column (string('icon')->nullable()) and render via a single <x-icon :class="$icon" /> component so you can normalise prefixes in one place later.

Wire up the events properly. The widget doesn't fire a native change, so anything reactive (Alpine, Livewire, your own preview) needs its own listener:

document.addEventListener('DOMContentLoaded', () => {
    $('.iconpicker').each(function () {
        const $input = $(this);

        $input.iconpicker({ selected: $input.val() });

        $input.on('iconpickerSelected', function (e) {
            const icon = e.iconpickerValue;            // e.g. "fa fa-user"
            $input.val(icon).trigger('change');        // keep Livewire/Alpine in sync
            $('#' + this.id + '-preview').attr('class', icon);
        });
    });
});

Triggering a native change on the underlying input is what makes it cooperate with wire:model and x-model.

Livewire: re-init after every morph. Livewire wipes the popover DOM on re-render. Register a hook once and re-run initialization on morph.updated:

document.addEventListener('livewire:init', () => {
    Livewire.hook('morph.updated', ({ el }) => {
        $(el).find('.iconpicker').each(function () {
            if (!$(this).data('iconpicker')) $(this).iconpicker();
        });
    });
});

Alternatively, keep the icon field in a plain (non-Livewire) form and submit normally — far less friction.

Multiple pickers on one page. Loop with $(this) inside .each() (as above) rather than calling .iconpicker() on the whole collection with shared options — otherwise selected is applied identically to every input.

Restrict the iconset. The picker ships a Font Awesome 4.7 icon list. If you only want a curated set (say, 40 navigation icons), pass your own array rather than forcing admins to scroll past 600:

const navIcons = ['home', 'user', 'cog', 'envelope', 'chart-bar', 'calendar'];
$('.iconpicker').iconpicker({
    iconset: [{ title: 'Navigation', icons: navIcons }],
});

This also makes the component feel intentional instead of like a dump of an entire icon library.

Validation on the server. Don't trust the posted class string — it ends up inside a class attribute. Use a FormRequest with a regex rule and a whitelist:

'icon' => ['nullable', 'string', 'max:100', Rule::in(config('icons.allowed'))],

At minimum: regex:/^fa[srb]? fa-[a-z0-9-]+$/. This kills the "><script> class of problem before it reaches Blade.

Seed and edit flows. For an edit form, set selected from the model and also pre-fill the input's value so the field isn't blank before JS boots. Progressive enhancement: the value is correct even if the JS bundle fails to load.

Testing. Add one Dusk/browser test that opens the picker, clicks an icon, and asserts the hidden value changed. Unit tests can't cover this widget, and the "it silently doesn't init" failure mode is invisible to feature tests.

Gotchas and Tips

  • Archived since 2018, built for Font Awesome 4 and Bootstrap 3. The generated markup is fa fa-name. If your app uses FA5/FA6 (fa-solid fa-user), the picker's class strings won't render. Two options: (a) include the FA4 shim/fontawesome.css compatibility layer, or (b) fork the iconset and prepend the right prefix — the picker's icon/template option lets you control the emitted class. Budget an afternoon for (b); it's a small fork, but it's your fork now.
  • Bootstrap 5 popovers are not API-compatible. The widget assumes Bootstrap 3's .popover() signature (functions vs. options object). If you're on BS5, expect to patch or to run Bootstrap 4 alongside it on admin pages only. There is no maintained BS5 port from this repo.
  • Popover clipping inside modals and overflow: hidden cards. The dropdown renders inside the input's parent by default and gets cut off. Fix with z-index CSS on .iconpicker-popover and position: fixed-friendly placement (placement: 'bottom'), or move the render target to body. Verify in an actual modal before shipping.
  • The iconpickerSelected payload is not the input value. Read e.iconpickerValue, not $(this).val() — the input value is only synced by the plugin itself. Mixing these up yields off-by-one-icon bugs where the preview lags a click behind.
  • Class name collisions. .iconpicker is not a namespaced selector; if your own CSS defines .iconpicker, you'll fight the widget's styles. Scope your field wrapper (.js-icon-field .iconpicker) and use a distinct init selector.
  • Re-initialisation throws or duplicates. Always guard with if (!$(el).data('iconpicker')) — or call .iconpicker('destroy') first. Duplicate popovers stacked invisibly behind each other are a classic symptom.
  • Search is client-side over the rendered set only. With a curated iconset, search is genuinely useful. With the full FA4 set plus a collapsed-by-default layout, users will say search "doesn't find" icons that exist — usually because the iconset was truncated.
  • Vite + jQuery interop. import $ from 'jquery' in an ES module gives you a module-scoped jQuery; the plugin attaches to window.jQuery. Always assign window.$ = window.jQuery = $ before importing the plugin, or use resolve.alias / optimizeDeps.include to guarantee a single instance.
  • Asset weight. The picker CSS + the full FA4 icon set is not tiny. If you only need 40 icons, your curated iconset also lets you drop the FA4 stylesheet from the admin bundle and ship only what the picker renders.
  • Upgrade path exists but isn't free. Because the project is archived, plan to either vendor it (copy dist/ into resources/ and pin it) or replace it. If your Laravel app leans heavily on Livewire/Alpine and FA6, a 100-line custom icon-select Blade component backed by a JSON icon list will usually be less work than keeping this alive. Adopt it where the Bootstrap 3/4 + FA4 combination already exists, not as a greenfield choice in 2024+.
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.
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
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect