Plugins
AdminLTE 4 for Laravel lazy-loads a handful of optional JavaScript libraries.
A plugin's assets are only emitted on pages that actually use it, keeping the
base layout lean. This is managed by the PluginManager singleton and the
@pluginStyles / @pluginScripts Blade directives.
How PluginManager works
PluginManager (src/Plugins/PluginManager.php) is registered as a singleton
seeded from the plugins array in config/adminlte.php. Because it is a
singleton, plugin state set during a request (for example by a component)
persists until the directives render.
Public API:
| Method | Description |
|---|---|
enable(string $plugin) |
Mark a plugin enabled for this request (only if it exists in config). |
disable(string $plugin) |
Mark a plugin disabled for this request. |
isEnabled(string $plugin) |
Whether the plugin is enabled (request override, else config enabled). |
has(string $plugin) |
Whether the plugin key exists in config. |
getCss(string $plugin) / getJs(string $plugin) |
Raw configured asset value when enabled, else null. |
getEnabledPlugins() |
All currently enabled plugins keyed by name. |
renderStyles() / renderScripts() |
HTML <link> / <script> tags for every enabled plugin. |
You can drive it directly from a view or service if needed:
@php app(\ColorlibHQ\AdminLte\Plugins\PluginManager::class)->enable('apexcharts'); @endphp
Config shape (css/js as string or array)
Each plugin is defined under the plugins key:
'plugins' => [
'apexcharts' => [
'enabled' => false,
'js' => 'vendor/apexcharts/apexcharts.min.js',
],
'jsvectormap' => [
'enabled' => false,
'css' => 'vendor/jsvectormap/jsvectormap.min.css',
'js' => [
'vendor/jsvectormap/jsvectormap.min.js',
'vendor/jsvectormap/maps/world.js',
],
],
],
enabled— whether the plugin loads by default on every page. Most ship asfalseand are turned on per-page by components.cssandjsaccept either a single string or an array of strings.renderStyles()/renderScripts()cast each to an array and emit one tag per file, in order. (Order matters — e.g. jsVectorMap loads the library first, then the world-map data file.)- A plugin may omit
cssorjsentirely (e.g. ApexCharts is JS-only).
All paths are passed through Laravel's asset() helper, so they resolve
relative to public/.
The @pluginStyles / @pluginScripts directives
These directives are registered in AdminLteServiceProvider and execute at
request time, not compile time:
Blade::directive('pluginStyles', fn () => "<?php echo app('...PluginManager')->renderStyles(); ?>");
Blade::directive('pluginScripts', fn () => "<?php echo app('...PluginManager')->renderScripts(); ?>");
The master layout places @pluginStyles in <head> and @pluginScripts at the
bottom of <body>. Because they evaluate during rendering, any plugin a
component enabled earlier in the same request is included.
Components auto-enable their plugins
Plugin-backed components call PluginManager::enable() in their constructor, so
simply using the component on a page emits the right assets — no config or manual
calls required:
| Component | Plugin enabled |
|---|---|
<x-adminlte-input-flatpickr> |
flatpickr |
<x-adminlte-input-tom-select> |
tom_select |
<x-adminlte-datatable> |
tabulator |
<x-adminlte-editor> |
quill |
<x-adminlte-chart> |
apexcharts |
<x-adminlte-vector-map> |
jsvectormap |
<x-adminlte-calendar> |
fullcalendar |
<x-adminlte-sortable> |
sortablejs |
<x-adminlte-kanban> |
sortablejs |
Bundled plugins
| Key | CSS | JS |
|---|---|---|
flatpickr |
vendor/flatpickr/flatpickr.min.css |
vendor/flatpickr/flatpickr.min.js |
tom_select |
vendor/tom-select/tom-select.bootstrap5.min.css |
vendor/tom-select/tom-select.complete.min.js |
tabulator |
vendor/tabulator-tables/tabulator.min.css |
vendor/tabulator-tables/tabulator.min.js |
quill |
vendor/quill/quill.snow.css |
vendor/quill/quill.min.js |
apexcharts |
— | vendor/apexcharts/apexcharts.min.js |
jsvectormap |
vendor/jsvectormap/jsvectormap.min.css |
vendor/jsvectormap/jsvectormap.min.js, vendor/jsvectormap/maps/world.js |
fullcalendar |
— | vendor/fullcalendar/index.global.min.js |
sortablejs |
— | vendor/sortablejs/sortablejs.min.js |
Note the config key for Tom Select is
tom_select(underscore).
How vendor files reach public/vendor
php artisan adminlte:install runs copyVendorFiles()
(src/Console/InstallCommand.php), which copies library files out of
node_modules into public/vendor. Keys are source paths relative to
node_modules; values are destination paths relative to public/vendor
(allowing a rename on copy). Missing sources are skipped silently.
From node_modules/... |
To public/vendor/... |
|---|---|
apexcharts/dist/apexcharts.min.js |
apexcharts/apexcharts.min.js |
jsvectormap/dist/jsvectormap.min.css |
jsvectormap/jsvectormap.min.css |
jsvectormap/dist/jsvectormap.min.js |
jsvectormap/jsvectormap.min.js |
jsvectormap/dist/maps/world.js |
jsvectormap/maps/world.js |
fullcalendar/index.global.min.js |
fullcalendar/index.global.min.js |
sortablejs/Sortable.min.js |
sortablejs/sortablejs.min.js |
flatpickr/dist/flatpickr.min.css |
flatpickr/flatpickr.min.css |
flatpickr/dist/flatpickr.min.js |
flatpickr/flatpickr.min.js |
tom-select/dist/css/tom-select.bootstrap5.min.css |
tom-select/tom-select.bootstrap5.min.css |
tom-select/dist/js/tom-select.complete.min.js |
tom-select/tom-select.complete.min.js |
tabulator-tables/dist/css/tabulator.min.css |
tabulator-tables/tabulator.min.css |
tabulator-tables/dist/js/tabulator.min.js |
tabulator-tables/tabulator.min.js |
quill/dist/quill.snow.css |
quill/quill.snow.css |
quill/dist/quill.js |
quill/quill.min.js |
admin-lte/dist/css/adminlte.rtl.min.css |
adminlte/css/adminlte.rtl.min.css |
Quill 2 ships a single minified UMD build named quill.js, so it's renamed on
copy to the quill.min.js path the config points at. The last entry is the RTL
stylesheet loaded by the master layout when layout_rtl is on. The FullCalendar
stylesheet ships inside this package (resources/vendor/) rather than npm, and
is copied from there.
Adding an optional plugin after install
Flatpickr, Tom Select, Tabulator and Quill are disabled by default and aren't part of the installer's npm step. Adding one takes two commands:
npm install -D quill@^2.0 # 1. fetch the library
php artisan adminlte:install --only=assets # 2. copy it into public/vendor
Missing sources are skipped silently, so --only=assets is safe to re-run at
any time and picks up whatever you've installed since.
Skipping step 2 is the classic failure: @pluginScripts emits
<script src="/vendor/quill/quill.min.js">, the file isn't there, the browser
404s, and <x-adminlte-editor> renders an empty box with nothing in the Laravel
log to explain it. php artisan adminlte:status lists each optional plugin so
you can see at a glance which ones are actually in place.
The app.js initializers
The published entry point resources/js/adminlte.js (from app.js.stub) imports
Bootstrap, OverlayScrollbars and admin-lte, then feature-detects the
globally-loaded plugin libraries and wires them up on DOM-ready. Because the
libraries are loaded as global <script> tags via @pluginScripts, each
initializer no-ops if its global is absent:
| Initializer | Trigger attribute | Notes |
|---|---|---|
initCharts() |
[data-apexchart] |
Reads data-apexchart-config (JSON), renders an ApexCharts instance. Wrapped in try/catch so one bad config can't break other charts. |
initVectorMaps() |
[data-jsvectormap] |
Requires an element id; reads data-jsvectormap-config. Warns if map data is missing. |
initCalendars() |
[data-fullcalendar] |
Reads data-fullcalendar-config; renders a FullCalendar. |
initSortables() |
[data-sortable] and [data-sortable-kanban] |
Generic lists read data-sortable-options; kanban lanes ([data-sortable-group]) share one group per board. |
initDatePickers() |
[data-flatpickr] |
Reads data-flatpickr-config; attaches a Flatpickr instance to the input. |
initTomSelects() |
[data-tom-select] |
Reads data-tom-select-config; upgrades the <select> to a Tom Select control. |
initDatatables() |
[data-tabulator-config] |
Builds a Tabulator table from the JSON config (columns, data, layout). |
initEditors() |
[data-quill] |
Reads data-quill-config, seeds the editor from the hidden input named by data-quill-target, and mirrors the editor's HTML back into that input on every change so a plain form POST submits it. An empty editor writes '' rather than Quill's <p><br></p>, so required / nullable validation behaves. |
initTreeviewA11y() |
sidebar treeview items | Mirrors AdminLTE's .menu-open class onto the toggle link's aria-expanded, so screen readers track submenu state. |
Each initializer marks processed elements with a data-*Ready flag so they
aren't initialized twice. Invalid JSON in a config attribute is logged with a
warning and treated as an empty config.