Vue Data Grid

ApexGrid is a Lit web component, so it works in Vue 3 as a custom element. This guide covers the Vite setup, property binding, imperative access, and events.

Installation

npm install apex-grid

Vite configuration

Tell Vue's template compiler to treat ApexGrid (and its sub-components) as custom elements, so it does not try to resolve them as Vue components. With Vite:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          // treat all tags with a dash as custom elements
          isCustomElement: (tag) => tag.includes('-'),
        },
      },
    }),
  ],
})

Usage

Register the element once with the side-effect import apex-grid/define, then use <apex-grid> in your template. Use the .prop modifier so Vue binds arrays and objects as JavaScript properties rather than HTML attributes.

<script setup>
import 'apex-grid/define'

const users = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob',   email: 'bob@example.com' },
]

const columns = [
  { key: 'id',    headerText: 'ID',    type: 'number' },
  { key: 'name',  headerText: 'Name',  sort: true, filter: true },
  { key: 'email', headerText: 'Email', sort: true },
]
</script>

<template>
  <apex-grid :columns.prop="columns" :data.prop="users"></apex-grid>
</template>

Binding complex data

When binding complex data such as objects and arrays, use the .prop modifier so Vue sets a DOM property instead of a (stringified) attribute:

<apex-grid :columns.prop="columns" :data.prop="users"></apex-grid>

See the Vue guide on passing DOM properties for more.

Accessing the grid imperatively

Put a template ref on the element to get the underlying DOM node, then call grid methods on it after mount:

<script setup>
import { ref, onMounted } from 'vue'
import 'apex-grid/define'
import type { ApexGrid } from 'apex-grid'

const gridEl = ref<ApexGrid>()

const users = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob',   email: 'bob@example.com' },
]
const columns = [
  { key: 'id',   headerText: 'ID',   type: 'number' },
  { key: 'name', headerText: 'Name', sort: true },
]

onMounted(() => {
  const grid = gridEl.value
  grid?.sort({ key: 'name', direction: 'ascending' })
})
</script>

<template>
  <apex-grid ref="gridEl" :columns.prop="columns" :data.prop="users"></apex-grid>
</template>

Listening to events

ApexGrid dispatches its events as native CustomEvents. The most reliable way to handle them in Vue is to attach a listener on the element ref in onMounted, reading the payload from event.detail:

<script setup>
import { ref, onMounted } from 'vue'
import 'apex-grid/define'
import type { ApexGrid } from 'apex-grid'

const gridEl = ref<ApexGrid>()

onMounted(() => {
  const grid = gridEl.value
  grid?.addEventListener('rowSelected', (e) => {
    console.log('selected:', (e as CustomEvent).detail)
  })
  grid?.addEventListener('sorted', (e) => {
    console.log('sorted:', (e as CustomEvent).detail)
  })
})
</script>

<template>
  <apex-grid ref="gridEl" :columns.prop="columns" :data.prop="users"></apex-grid>
</template>

Template v-on binding also works in a build setup (SFC templates preserve the event-name case), for example @rowSelected="onRowSelected". The event name is case-sensitive, so match it exactly; the addEventListener approach above avoids any casing ambiguity.

Commonly used events dispatched by ApexGrid (the -ing / -Changing variants fire before the operation and are cancellable; see the React guide for the complete list):

EventDetail
rowSelectedThe selected row data
cellValueChangedUpdated cell value and row data
sortedActive sort expression
filteredActive filter state
pageChangedNew page index and size