✨ feature: Data table component added
This commit is contained in:
parent
a4bbfeb9ad
commit
3d6b27c13c
414
src/components/table/VDataTable.vue
Normal file
414
src/components/table/VDataTable.vue
Normal file
|
@ -0,0 +1,414 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import DataTable from 'primevue/datatable';
|
||||||
|
import type { DataTableProps, DataTableSlots } from 'primevue/datatable';
|
||||||
|
import { useId, ref, watch, computed } from 'vue';
|
||||||
|
|
||||||
|
export interface IVDataTable extends Partial<Omit<DataTableProps, 'pt' | 'dt' | 'ptOptions' | 'unstyled'>>{
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<IVDataTable>(), {
|
||||||
|
id: () => useId(),
|
||||||
|
title: '',
|
||||||
|
selection: undefined,
|
||||||
|
paginator: false,
|
||||||
|
rowsPerPageOptions: undefined,
|
||||||
|
rows: 0,
|
||||||
|
value: undefined,
|
||||||
|
dataKey: undefined,
|
||||||
|
showGridlines: false,
|
||||||
|
stripedRows: false,
|
||||||
|
first: 0,
|
||||||
|
totalRecords: 0,
|
||||||
|
pageLinkSize: 5,
|
||||||
|
paginatorPosition: 'bottom',
|
||||||
|
paginatorTemplate: undefined,
|
||||||
|
alwaysShowPaginator:true,
|
||||||
|
currentPageReportTemplate: '({currentPage} de {totalPages})',
|
||||||
|
lazy: false,
|
||||||
|
loading: false,
|
||||||
|
sortField: undefined,
|
||||||
|
sortOrder: undefined,
|
||||||
|
nullSortOrder: 1,
|
||||||
|
defaultSortOrder: 1,
|
||||||
|
sortMode: 'single',
|
||||||
|
removableSort: false,
|
||||||
|
filters: undefined,
|
||||||
|
filterDisplay: undefined,
|
||||||
|
globalFilterFields: undefined,
|
||||||
|
filterLocale: undefined,
|
||||||
|
selectionMode: undefined,
|
||||||
|
compareSelectionBy: 'deepEquals',
|
||||||
|
metaKeySelection: false,
|
||||||
|
contextMenu: false,
|
||||||
|
contextMenuSelection: undefined,
|
||||||
|
selectAll: undefined,
|
||||||
|
rowHover: false,
|
||||||
|
csvSeparator: ',',
|
||||||
|
exportFilename: 'download',
|
||||||
|
exportFunction: undefined,
|
||||||
|
resizableColumns: false,
|
||||||
|
columnResizeMode: 'fit',
|
||||||
|
reorderableColumns: false,
|
||||||
|
expandedRows: undefined,
|
||||||
|
expandedRowIcon: undefined,
|
||||||
|
collapsedRowIcon: undefined,
|
||||||
|
rowGroupMode: undefined,
|
||||||
|
groupRowsBy: undefined,
|
||||||
|
expandableRowGroups: false,
|
||||||
|
expandedRowGroups: undefined,
|
||||||
|
stateStorage: 'session',
|
||||||
|
stateKey: undefined,
|
||||||
|
editMode: undefined,
|
||||||
|
editingRows: undefined,
|
||||||
|
rowClass: undefined,
|
||||||
|
rowStyle: undefined,
|
||||||
|
scrollable: false,
|
||||||
|
scrollHeight: undefined,
|
||||||
|
virtualScrollerOptions: undefined,
|
||||||
|
frozenValue: undefined,
|
||||||
|
breakpoint: '960px',
|
||||||
|
showHeaders: true,
|
||||||
|
highlightOnSelect: false,
|
||||||
|
size: undefined,
|
||||||
|
tableClass: undefined,
|
||||||
|
tableProps: undefined,
|
||||||
|
tableStyle: undefined,
|
||||||
|
filterButtonProps: undefined,
|
||||||
|
editButtonProps: undefined,
|
||||||
|
multiSortMeta: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
const slots = defineSlots<DataTableSlots>();
|
||||||
|
|
||||||
|
const dataTableSlotKeys = [
|
||||||
|
'header',
|
||||||
|
'footer',
|
||||||
|
'empty',
|
||||||
|
'groupheader',
|
||||||
|
'groupfooter',
|
||||||
|
'loading',
|
||||||
|
'expansion',
|
||||||
|
'loadingicon',
|
||||||
|
'reorderindicatorupicon', // deprecated
|
||||||
|
'rowreorderindicatorupicon',
|
||||||
|
'reorderindicatordownicon', // deprecated
|
||||||
|
'rowreorderindicatordownicon',
|
||||||
|
'rowgrouptogglericon',
|
||||||
|
'paginatorcontainer',
|
||||||
|
'paginatorstart',
|
||||||
|
'paginatorend',
|
||||||
|
'paginatorfirstpagelinkicon',
|
||||||
|
'paginatorprevpagelinkicon',
|
||||||
|
'paginatornextpagelinkicon',
|
||||||
|
'paginatorlastpagelinkicon',
|
||||||
|
'paginatorrowsperpagedropdownicon',
|
||||||
|
'paginatorjumptopagedropdownicon'
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const availableSlots = computed(() =>
|
||||||
|
dataTableSlotKeys.filter((key) => !!slots[key]).map((key) => [key, slots[key]])
|
||||||
|
);
|
||||||
|
|
||||||
|
const dataTableRef = ref();
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
exportCSV: () => dataTableRef.value.exportCSV()
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
'update:selection',
|
||||||
|
'update:rows',
|
||||||
|
'update:sortField',
|
||||||
|
'update:sortOrder',
|
||||||
|
'update:multiSortMeta',
|
||||||
|
'update:contextMenuSelection',
|
||||||
|
'update:expandedRows',
|
||||||
|
'update:expandedRowGroups',
|
||||||
|
'update:filters',
|
||||||
|
'update:editingRows',
|
||||||
|
'update:first',
|
||||||
|
'page',
|
||||||
|
'sort',
|
||||||
|
'row-select',
|
||||||
|
'row-unselect',
|
||||||
|
'filter',
|
||||||
|
'value-change',
|
||||||
|
'row-click',
|
||||||
|
'row-dbclick',
|
||||||
|
'row-contextmenu',
|
||||||
|
'row-select-all',
|
||||||
|
'row-unselect-all',
|
||||||
|
'select-all-change',
|
||||||
|
'column-resize-end',
|
||||||
|
'column-reorder',
|
||||||
|
'row-reorder',
|
||||||
|
'row-expand',
|
||||||
|
'row-collapse',
|
||||||
|
'rowgroup-expand',
|
||||||
|
'rowgroup-collapse',
|
||||||
|
'cell-edit-init',
|
||||||
|
'cell-edit-complete',
|
||||||
|
'cell-edit-cancel',
|
||||||
|
'row-edit-init',
|
||||||
|
'row-edit-save',
|
||||||
|
'row-edit-cancel',
|
||||||
|
'state-restore',
|
||||||
|
'state-save',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const localSelection = ref(props.selection);
|
||||||
|
watch(() => props.selection, (newVal) => {
|
||||||
|
if(localSelection.value !== newVal) {
|
||||||
|
localSelection.value = newVal;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
watch(localSelection, (newVal) => {
|
||||||
|
if(props.selection !== newVal){
|
||||||
|
emit('update:selection', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localRows = ref(props.rows);
|
||||||
|
watch(() => props.rows, (newVal) => {
|
||||||
|
if(localRows.value !== newVal){
|
||||||
|
localRows.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localRows, (newVal) => {
|
||||||
|
if(props.rows !== newVal){
|
||||||
|
emit('update:rows', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localFirst = ref(props.first);
|
||||||
|
watch(() => props.first, (newVal) => {
|
||||||
|
if(localFirst.value !== newVal){
|
||||||
|
localFirst.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localFirst, (newVal) => {
|
||||||
|
if(props.first !== newVal){
|
||||||
|
emit('update:first', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localSortField = ref(props.sortField);
|
||||||
|
watch(() => props.sortField, (newVal) => {
|
||||||
|
if(localSortField.value !== newVal){
|
||||||
|
localSortField.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localSortField, (newVal) => {
|
||||||
|
if(props.sortField !== newVal){
|
||||||
|
emit('update:sortField', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localSortOrder = ref(props.sortOrder);
|
||||||
|
watch(() => props.sortOrder, (newVal) => {
|
||||||
|
if(localSortOrder.value !== newVal){
|
||||||
|
localSortOrder.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localSortOrder, (newVal) => {
|
||||||
|
if(props.sortOrder !== newVal){
|
||||||
|
emit('update:sortOrder', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localMultiSortMeta = ref(props.multiSortMeta);
|
||||||
|
watch(() => props.multiSortMeta, (newVal) => {
|
||||||
|
if(localMultiSortMeta.value !== newVal){
|
||||||
|
localMultiSortMeta.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localMultiSortMeta, (newVal) => {
|
||||||
|
if(props.multiSortMeta !== newVal){
|
||||||
|
emit('update:multiSortMeta', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localContextMenuSelection = ref(props.contextMenuSelection);
|
||||||
|
watch(() => props.contextMenuSelection, (newVal) => {
|
||||||
|
if(localContextMenuSelection.value !== newVal){
|
||||||
|
localContextMenuSelection.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localContextMenuSelection, (newVal) => {
|
||||||
|
if(props.contextMenuSelection){
|
||||||
|
emit('update:contextMenuSelection', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localExpandedRows = ref(props.expandedRows);
|
||||||
|
watch(() => props.expandedRows, (newVal) => {
|
||||||
|
if(localExpandedRows.value !== newVal){
|
||||||
|
localExpandedRows.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localExpandedRows, (newVal) => {
|
||||||
|
if(props.expandedRows !== newVal){
|
||||||
|
emit('update:expandedRows', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localExpandedRowGroups = ref(props.expandedRowGroups);
|
||||||
|
watch(() => props.expandedRowGroups, (newVal) => {
|
||||||
|
if(localExpandedRowGroups.value !== newVal){
|
||||||
|
localExpandedRowGroups.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localExpandedRowGroups, (newVal) => {
|
||||||
|
if(props.expandedRowGroups !== newVal){
|
||||||
|
emit('update:expandedRowGroups', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localFilters = ref(props.filters);
|
||||||
|
watch(() => props.filters, (newVal) => {
|
||||||
|
if(localFilters.value !== newVal){
|
||||||
|
localFilters.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localFilters, (newVal) => {
|
||||||
|
if(props.filters !== newVal){
|
||||||
|
emit('update:filters', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const localEditingRows = ref(props.editingRows);
|
||||||
|
watch(() => props.editingRows, (newVal) => {
|
||||||
|
if(localEditingRows.value = newVal){
|
||||||
|
localEditingRows.value = newVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(localEditingRows, (newVal) => {
|
||||||
|
if(props.editingRows !== newVal){
|
||||||
|
emit('update:editingRows', newVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DataTable
|
||||||
|
:id="`datatable-${props.id}`"
|
||||||
|
role="table"
|
||||||
|
ref="dataTableRef"
|
||||||
|
:value="props.value"
|
||||||
|
:paginator="props.paginator"
|
||||||
|
:rowsPerPageOptions="props.rowsPerPageOptions"
|
||||||
|
:data-key="props.dataKey"
|
||||||
|
:show-gridlines="props.showGridlines"
|
||||||
|
:striped-rows="props.stripedRows"
|
||||||
|
:total-records="props.totalRecords"
|
||||||
|
:page-link-size="props.pageLinkSize"
|
||||||
|
:paginator-position="props.paginatorPosition"
|
||||||
|
:paginator-template="props.paginatorTemplate"
|
||||||
|
:always-show-paginator="props.alwaysShowPaginator"
|
||||||
|
:current-page-report-template="props.currentPageReportTemplate"
|
||||||
|
:lazy="props.lazy"
|
||||||
|
:loading="props.loading"
|
||||||
|
:nullSortOrder="props.nullSortOrder"
|
||||||
|
:defaultSortOrder="props.defaultSortOrder"
|
||||||
|
:sortMode="props.sortMode"
|
||||||
|
:removableSort="props.removableSort"
|
||||||
|
:filterDisplay="props.filterDisplay"
|
||||||
|
:globalFilterFields="props.globalFilterFields"
|
||||||
|
:filterLocale="props.filterLocale"
|
||||||
|
:selectionMode="props.selectionMode"
|
||||||
|
:compareSelectionBy="props.compareSelectionBy"
|
||||||
|
:metaKeySelection="props.metaKeySelection"
|
||||||
|
:contextMenu="props.contextMenu"
|
||||||
|
:selectAll="props.selectAll"
|
||||||
|
:rowHover="props.rowHover"
|
||||||
|
:csvSeparator="props.csvSeparator"
|
||||||
|
:exportFilename="props.exportFilename"
|
||||||
|
:exportFunction="props.exportFunction"
|
||||||
|
:resizableColumns="props.resizableColumns"
|
||||||
|
:columnResizeMode="props.columnResizeMode"
|
||||||
|
:reorderableColumns="props.reorderableColumns"
|
||||||
|
:expandedRowIcon="props.expandedRowIcon"
|
||||||
|
:collapsedRowIcon="props.collapsedRowIcon"
|
||||||
|
:rowGroupMode="props.rowGroupMode"
|
||||||
|
:groupRowsBy="props.groupRowsBy"
|
||||||
|
:expandableRowGroups="props.expandableRowGroups"
|
||||||
|
:stateStorage="props.stateStorage"
|
||||||
|
:stateKey="props.stateKey"
|
||||||
|
:editMode="props.editMode"
|
||||||
|
:rowClass="props.rowClass"
|
||||||
|
:rowStyle="props.rowStyle"
|
||||||
|
:scrollable="props.scrollable"
|
||||||
|
:scrollHeight="props.scrollHeight"
|
||||||
|
:virtualScrollerOptions="props.virtualScrollerOptions"
|
||||||
|
:frozenValue="props.frozenValue"
|
||||||
|
:breakpoint="props.breakpoint"
|
||||||
|
:showHeaders="props.showHeaders"
|
||||||
|
:highlightOnSelect="props.highlightOnSelect"
|
||||||
|
:size="props.size"
|
||||||
|
:tableClass="props.tableClass"
|
||||||
|
:tableProps="props.tableProps"
|
||||||
|
:tableStyle="props.tableStyle"
|
||||||
|
:filterButtonProps="props.filterButtonProps"
|
||||||
|
:editButtonProps="props.editButtonProps"
|
||||||
|
style="width: 100%; height: fit-content;"
|
||||||
|
v-model:selection="localSelection"
|
||||||
|
v-model:rows="localRows"
|
||||||
|
v-model:first="localFirst"
|
||||||
|
v-model:sortField="localSortField"
|
||||||
|
v-model:sortOrder="localSortOrder"
|
||||||
|
v-model:filters="localFilters"
|
||||||
|
v-model:contextMenuSelection="localContextMenuSelection"
|
||||||
|
v-model:expandedRows="localExpandedRows"
|
||||||
|
v-model:expandedRowGroups="localExpandedRowGroups"
|
||||||
|
v-model:editingRows="localEditingRows"
|
||||||
|
v-model:multi-sort-meta="localMultiSortMeta"
|
||||||
|
@update:selection="emit('update:selection', $event)"
|
||||||
|
@update:context-menu-selection="emit('update:contextMenuSelection', $event)"
|
||||||
|
@update:editing-rows="emit('update:editingRows', $event)"
|
||||||
|
@update:expanded-row-groups="emit('update:expandedRowGroups', $event)"
|
||||||
|
@update:filters="emit('update:filters', $event)"
|
||||||
|
@update:first="emit('update:first', $event)"
|
||||||
|
@update:multi-sort-meta="emit('update:multiSortMeta', $event)"
|
||||||
|
@update:rows="emit('update:rows', $event)"
|
||||||
|
@update:sort-field="emit('update:sortField', $event)"
|
||||||
|
@update:sort-order="emit('update:sortOrder', $event)"
|
||||||
|
@page="emit('page', $event)"
|
||||||
|
@sort="emit('sort', $event)"
|
||||||
|
@rowSelect="emit('row-select', $event)"
|
||||||
|
@rowUnselect="emit('row-unselect', $event)"
|
||||||
|
@filter="emit('filter', $event)"
|
||||||
|
@valueChange="emit('value-change', $event)"
|
||||||
|
@rowClick="emit('row-click', $event)"
|
||||||
|
@rowCollapse="emit('row-collapse', $event)"
|
||||||
|
@rowContextmenu="emit('row-contextmenu', $event)"
|
||||||
|
@rowDblclick="emit('row-dbclick', $event)"
|
||||||
|
@rowEditCancel="emit('row-edit-cancel', $event)"
|
||||||
|
@rowEditInit="emit('row-edit-init', $event)"
|
||||||
|
@rowEditSave="emit('row-edit-save', $event)"
|
||||||
|
@rowExpand="emit('row-expand', $event)"
|
||||||
|
@rowReorder="emit('row-reorder', $event)"
|
||||||
|
@rowSelectAll="emit('row-select-all', $event)"
|
||||||
|
@rowUnselectAll="emit('row-unselect-all', $event)"
|
||||||
|
@rowgroupCollapse="emit('rowgroup-collapse', $event)"
|
||||||
|
@rowgroupExpand="emit('rowgroup-expand', $event)"
|
||||||
|
@columnReorder="emit('column-reorder', $event)"
|
||||||
|
@columnResizeEnd="emit('column-resize-end', $event)"
|
||||||
|
@cellEditCancel="emit('cell-edit-cancel', $event)"
|
||||||
|
@cellEditComplete="emit('cell-edit-complete', $event)"
|
||||||
|
@cellEditInit="emit('cell-edit-init', $event)"
|
||||||
|
@stateRestore="emit('state-restore', $event)"
|
||||||
|
@stateSave="emit('state-save', $event)"
|
||||||
|
@selectAllChange="emit('select-all-change', $event)"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="([name]) in availableSlots"
|
||||||
|
:key="name"
|
||||||
|
v-slot:[name]="slotProps"
|
||||||
|
>
|
||||||
|
<slot :name="name" v-bind="slotProps" />
|
||||||
|
</template>
|
||||||
|
</DataTable>
|
||||||
|
</template>
|
Loading…
Reference in New Issue
Block a user