Plugin components

[object Object]

Plugin components wrap heavy third-party libraries (charts, calendars, data grids, editors, drag-and-drop). They are exported from the @adminlte/vue/plugins entry — separate from the core components — so the plugin libs stay out of the default import. Each wrapper renders a host element, then await import(...)s its library inside onMounted and destroys the instance in onBeforeUnmount.

Installation and usage

Because these wrappers load their library only in the browser, the consuming app must install the matching peer dependency and its CSS, and the component must run client-side only.

Install the peer lib + CSS

Each wrapper depends on its own (optional) peer library. Install only the ones you use, and import the library's stylesheet yourself.

# install the peer lib for the wrapper(s) you use
pnpm add apexcharts          # LteApexChart, LteSparklineChart
pnpm add @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction  # LteCalendar
pnpm add tabulator-tables    # LteDatatable
pnpm add quill               # LteEditor
pnpm add tom-select          # LteTomSelect
pnpm add flatpickr           # LteFlatpickr
pnpm add jsvectormap         # LteVectorMap
pnpm add sortablejs          # LteSortable, LteKanban

Wrap in <ClientOnly>

In a Nuxt (SSR) app, wrap every plugin component in <ClientOnly> so it only mounts in the browser. A #fallback keeps the layout stable during hydration.

<template>
  <ClientOnly>
    <LteApexChart type="line" :series="series" />
    <template #fallback>
      <div style="height: 350px" />
    </template>
  </ClientOnly>
</template>

<script setup lang="ts">
const series = [{ name: 'Sales', data: [30, 40, 35, 50, 49, 60, 70] }]
</script>

LteApexChart

Wraps ApexCharts. The host options are built as { chart: { type, height, width }, series }, with options merged over the top. The chart updates reactively when series, options, type, height, or width change.

series is watched by reference: replace the array immutably (series = [...]) to trigger an update. Set deep-watch if you mutate it in place instead — that trades a recursive traversal of the dataset on every change for the convenience.

Props

NameTypeDefaultDescription
seriesunknown[]— (required)The chart series data.
typestring'line'ApexCharts chart type (e.g. bar, area, donut).
optionsApexOptionsundefinedExtra ApexCharts options merged over { chart: { type, height }, series }.
heightnumber | string350Chart height.
widthnumber | stringundefinedChart width.
deepWatchbooleanfalseWatch series deeply (for in-place mutation).
<LteApexChart
  type="bar"
  :series="[{ name: 'Net Profit', data: [44, 55, 57, 56] }]"
  :options="{ xaxis: { categories: ['Q1', 'Q2', 'Q3', 'Q4'] } }"
/>

LteCalendar

Wraps FullCalendar with the daygrid and interaction plugins. The header toolbar and editable: true are preset; pass options to override or extend the FullCalendar config. Updating events reloads the event sources (watched by reference — replace the array immutably, or set deep-watch); changing initialView after mount calls calendar.changeView(), and changed options keys are applied via calendar.setOption().

Props

NameTypeDefaultDescription
eventsEventInput[][]FullCalendar event inputs.
initialViewstring'dayGridMonth'The calendar view (reactive after mount).
optionsPartial<CalendarOptions>undefinedExtra FullCalendar options spread over the defaults.
deepWatchbooleanfalseWatch events deeply (for in-place mutation).

Emits

NamePayloadDescription
dateClickDateClickArgA calendar date was clicked.
eventClickEventClickArgAn event was clicked.
eventDropEventDropArgAn event was dragged to a new date.

Exposed

NameReturnsDescription
getApi()Calendar | nullThe underlying FullCalendar instance (null until mounted).
<template>
  <ClientOnly>
    <LteCalendar ref="cal" :events="events" @event-click="onEventClick" />
  </ClientOnly>
</template>

<script setup lang="ts">
const cal = ref()
const events = [{ title: 'Meeting', date: '2026-06-01' }]
function onEventClick(arg) {
  console.log(arg.event.title)
}
</script>

LteDatatable

Wraps Tabulator. The host options default to { layout: 'fitColumns', height, columns, data }, with options merged over the top. Updating data calls Tabulator's replaceData (watched by reference — replace the array immutably, or set deep-watch); updating columns calls setColumns. options and height are mount-only — use getTable() for runtime tweaks.

Props

NameTypeDefaultDescription
columnsArray<Record<string, unknown>>[]Tabulator column definitions (reactive after mount).
dataunknown[][]Row data.
optionsRecord<string, unknown>undefinedExtra Tabulator options merged over { columns, data }. Mount-only.
heightstringundefinedTable height. Mount-only.
deepWatchbooleanfalseWatch data deeply (for in-place mutation).

Emits

NamePayloadDescription
readytableFired on Tabulator's tableBuilt; receives the Tabulator instance.

Exposed

NameReturnsDescription
getTable()Tabulator | nullThe underlying Tabulator instance (null until mounted).
<LteDatatable
  :columns="[{ title: 'Name', field: 'name' }, { title: 'Age', field: 'age' }]"
  :data="[{ name: 'Ada', age: 36 }, { name: 'Linus', age: 54 }]"
  @ready="(table) => console.log(table)"
/>

LteSortable

A generic drag-to-reorder list backed by SortableJS. It renders a configurable host tag containing your default slot and emits update:modelValue with the reordered array. Use v-model to bind the list.

Props

NameTypeDefaultDescription
modelValueT[][]v-model — the ordered list.
tagstring'div'The host element tag to render.
optionsOptions (sortablejs)undefinedExtra SortableJS options (merged over { animation: 150 }).

Emits

NamePayloadDescription
update:modelValueT[]The reordered list.
endSortableEventThe underlying SortableJS onEnd event.
<template>
  <LteSortable v-model="items" tag="ul" class="list-group">
    <li v-for="item in items" :key="item" class="list-group-item">{{ item }}</li>
  </LteSortable>
</template>

<script setup lang="ts">
const items = ref(['Alpha', 'Bravo', 'Charlie'])
</script>

LteKanban

A multi-column drag-and-drop board built on SortableJS (shared group: 'kanban', so cards move between columns). It renders Bootstrap cards per column and emits move when a card is dropped. The KanbanCard and KanbanColumn types are exported from @adminlte/vue/plugins.

Types

interface KanbanCard {
  id: string
  title: string
  text?: string
}
interface KanbanColumn {
  id: string
  title: string
  theme?: BootstrapTheme
  cards: KanbanCard[]
}

Props

NameTypeDefaultDescription
columnsKanbanColumn[]— (required)The board columns and their cards.

Emits

NamePayloadDescription
move{ card: string; from: string; to: string; newIndex: number }A card was moved; identifies the card and source/target column ids and its new index.
<template>
  <LteKanban :columns="columns" @move="onMove" />
</template>

<script setup lang="ts">
import type { KanbanColumn } from '@adminlte/vue/plugins'

const columns = ref<KanbanColumn[]>([
  { id: 'todo', title: 'To Do', theme: 'primary', cards: [{ id: '1', title: 'Draft spec' }] },
  { id: 'done', title: 'Done', theme: 'success', cards: [] },
])

function onMove(payload) {
  console.log(payload.card, payload.from, '->', payload.to, payload.newIndex)
}
</script>

Other wrappers

The plugins entry also exports these wrappers, which follow the same dynamic-import / <ClientOnly> pattern:

ComponentPeer library
LteSparklineChartapexcharts
LteEditorquill
LteTomSelecttom-select
LteFlatpickrflatpickr
LteVectorMapjsvectormap