Migrating from UITable to HighRise DataTable
HighRise HLDataTable is built on TanStack Table and pairs with HLDataTableWrapper for header controls (search, column toggles, layouts, pagination container). API shape changes around columns, selection, search, and pagination.
Component Implementation Changes
Import Changes
diff
- import { UITable } from '@gohighlevel/ghl-ui'
+ import { HLDataTable, HLDataTableWrapper } from '@platform-ui/highrise'Key Differences
- Columns use
id,header,accessorKey, andcellFormatter(row)instead ofkey/title/render. - Selection:
checkedRowKeys→selectedRows(array of IDs).rowUniqueIddefaults to"id". - Search: use
HLDataTableWrapperwithshow-header+show-global-searchand handle@update:global-filter(noenableTextSearch). - Pagination: drive
HLPaginationfrom TanStack state (page size/index) inside the wrapperfooterslot. - Empty slot:
empty→no-data. - Reordering/resizing via props (
rowReordering,columnReordering,columnResizing) and emits (update:row-reordered,update:column-order).
Props Mapping
| ghl-ui Prop / Pattern | HighRise Equivalent | Notes |
|---|---|---|
columns: [{ key, title, render }] | columns: [{ id, header, accessorKey, cellFormatter, sortingFn?, filterFn? }] | header accepts string/VNode/fn; cellFormatter receives TanStack row |
checkedRowKeys | selectedRows | Pair with rowUniqueId if your key is not id |
enableTextSearch | show-header + show-global-search on wrapper | Emits update:global-filter |
@update:searchText | @update:global-filter (wrapper) | Receives search string |
showSizePicker, pageSizes, page, pageCount | Drive HLPagination manually | Use TanStack state: table?.getState().pagination |
empty slot | no-data slot | Use HLEmpty or custom content |
Row click via @row-click | @table-row-clicked | Emits (rowData) |
Events (commonly used)
HLDataTableWrapper:update:global-filter,update:column-checked,update:column-freeze,update:page-size,update:current-layout,update:table-layout,update:table-layout-as,update:column-reorder,update:table-height-selected-option.HLDataTable:update:cell-value,update:column-order,update:row-reordered,table-row-clicked,scroll,no-data.
Examples
Basic DataTable
vue
<template>
<HLDataTable
:columns="columns"
:data="rows"
:row-height="'auto'"
:selected-rows="selectedRows"
row-unique-id="email"
@table-row-clicked="handleRowClick"
/>
</template>
<script setup>
import { h, ref } from 'vue'
import { HLDataTable } from '@platform-ui/highrise'
const selectedRows = ref([])
const rows = [
{ email: '[email protected]', name: 'Alice' },
{ email: '[email protected]', name: 'Bob' },
]
const columns = [
{
id: 'name',
header: 'Name',
accessorKey: 'name',
cellFormatter: row => row.row.original.name,
},
{
id: 'email',
header: () => h('span', { class: 'text-gray-500' }, 'Email'),
accessorKey: 'email',
cellFormatter: row => row.row.original.email,
},
]
const handleRowClick = row => {
console.log('clicked', row)
}
</script>With Search and Pagination
vue
<template>
<HLDataTableWrapper
id="users-table"
:show-header="true"
:show-global-search="true"
:responsive-column-width="true"
max-width="100%"
@update:global-filter="val => (globalFilter = val)"
>
<template #footer>
<HLPagination
:current-page="table?.getState().pagination.pageIndex + 1"
:per-page="table?.getState().pagination.pageSize"
:item-count="table?.getFilteredRowModel().rows.length || 0"
:show-per-page-drop-down="true"
@update:page="page => table?.setPageIndex(page - 1)"
@update:per-page="pageSize => table?.setPageSize(pageSize)"
/>
</template>
<HLDataTable
ref="tableRef"
:columns="columns"
:data="rows"
:selected-rows="selectedRows"
row-unique-id="id"
@update:row-reordered="handleReorder"
>
<template #no-data>
<HLEmpty description="No rows match the current filters" />
</template>
</HLDataTable>
</HLDataTableWrapper>
</template>
<script setup>
import { ref, computed } from 'vue'
import { HLDataTable, HLDataTableWrapper, HLPagination, HLEmpty } from '@platform-ui/highrise'
const tableRef = ref(null)
const table = computed(() => tableRef.value?.table)
const selectedRows = ref([])
const globalFilter = ref('')
const rows = ref([])
const handleReorder = payload => {
console.log('reordered rows', payload)
}
</script>Best Practices
- Always include both
idandaccessorKeyon columns; keep them unique. - Keep row IDs in
rowUniqueIdaligned with your data shape; passselectedRowsusing that key. - Use
HLDataTableWrapperto wire search/header controls; connectupdate:global-filterto your data source. - Drive pagination from TanStack state; avoid mixing legacy
page/pageCountprops. - Provide
no-dataandfooterslots to keep empty states and pagination consistent.