Refactor #3924 - For DataTable

This commit is contained in:
Tuğçe Küçükoğlu 2023-05-08 17:08:06 +03:00
parent bf9d7c0380
commit 8b9d1d8eb3
15 changed files with 652 additions and 113 deletions

View file

@ -377,6 +377,12 @@ const DataTableProps = [
type: 'string', type: 'string',
default: 'null', default: 'null',
description: 'Style class of the table element.' description: 'Style class of the table element.'
},
{
name: 'pt',
type: 'any',
default: 'null',
description: 'Uses to pass attributes to DOM elements inside the component.'
} }
]; ];

View file

@ -19,6 +19,7 @@ import { ColorPickerPassThroughOptions } from '../colorpicker';
import { ConfirmDialogPassThroughOptions } from '../confirmdialog'; import { ConfirmDialogPassThroughOptions } from '../confirmdialog';
import { ConfirmPopupPassThroughOptions } from '../confirmpopup'; import { ConfirmPopupPassThroughOptions } from '../confirmpopup';
import { ContextMenuPassThroughOptions } from '../contextmenu'; import { ContextMenuPassThroughOptions } from '../contextmenu';
import { DataTablePassThroughOptions } from '../datatable';
import { DeferredContentPassThroughOptions } from '../deferredcontent'; import { DeferredContentPassThroughOptions } from '../deferredcontent';
import { DialogPassThroughOptions } from '../dialog'; import { DialogPassThroughOptions } from '../dialog';
import { DividerPassThroughOptions } from '../divider'; import { DividerPassThroughOptions } from '../divider';
@ -108,6 +109,7 @@ interface PrimeVuePTOptions {
confirmdialog?: ConfirmDialogPassThroughOptions; confirmdialog?: ConfirmDialogPassThroughOptions;
confirmpopup?: ConfirmPopupPassThroughOptions; confirmpopup?: ConfirmPopupPassThroughOptions;
contextmenu?: ContextMenuPassThroughOptions; contextmenu?: ContextMenuPassThroughOptions;
datatable?: DataTablePassThroughOptions;
deferredcontent?: DeferredContentPassThroughOptions; deferredcontent?: DeferredContentPassThroughOptions;
divider?: DividerPassThroughOptions; divider?: DividerPassThroughOptions;
dialog?: DialogPassThroughOptions; dialog?: DialogPassThroughOptions;

View file

@ -1,9 +1,9 @@
<template> <template>
<td v-if="loading" :style="containerStyle" :class="containerClass"> <td v-if="loading" :style="containerStyle" :class="containerClass" role="cell" v-bind="ptm('bodyCell')">
<component :is="column.children.loading" :data="rowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" :loadingOptions="loadingOptions" /> <component :is="column.children.loading" :data="rowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" :loadingOptions="loadingOptions" />
</td> </td>
<td v-else :style="containerStyle" :class="containerClass" @click="onClick" @keydown="onKeyDown" role="cell"> <td v-else :style="containerStyle" :class="containerClass" @click="onClick" @keydown="onKeyDown" role="cell" v-bind="ptm('bodyCell')">
<span v-if="responsiveLayout === 'stack'" class="p-column-title">{{ columnProp('header') }}</span> <span v-if="responsiveLayout === 'stack'" class="p-column-title" v-bind="ptm('columnTitle')">{{ columnProp('header') }}</span>
<component v-if="column.children && column.children.body && !d_editing" :is="column.children.body" :data="rowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" :editorInitCallback="editorInitCallback" /> <component v-if="column.children && column.children.body && !d_editing" :is="column.children.body" :data="rowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" :editorInitCallback="editorInitCallback" />
<component <component
v-else-if="column.children && column.children.editor && d_editing" v-else-if="column.children && column.children.editor && d_editing"
@ -18,7 +18,7 @@
/> />
<component v-else-if="column.children && column.children.body && !column.children.editor && d_editing" :is="column.children.body" :data="editingRowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" /> <component v-else-if="column.children && column.children.body && !column.children.editor && d_editing" :is="column.children.body" :data="editingRowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" />
<template v-else-if="columnProp('selectionMode')"> <template v-else-if="columnProp('selectionMode')">
<DTRadioButton v-if="columnProp('selectionMode') === 'single'" :value="rowData" :name="name" :checked="selected" @change="toggleRowWithRadio($event, rowIndex)" /> <DTRadioButton v-if="columnProp('selectionMode') === 'single'" :value="rowData" :name="name" :checked="selected" @change="toggleRowWithRadio($event, rowIndex)" :pt="pt" />
<DTCheckbox <DTCheckbox
v-else-if="columnProp('selectionMode') === 'multiple'" v-else-if="columnProp('selectionMode') === 'multiple'"
:value="rowData" :value="rowData"
@ -26,31 +26,32 @@
:rowCheckboxIconTemplate="column.children && column.children.rowcheckboxicon" :rowCheckboxIconTemplate="column.children && column.children.rowcheckboxicon"
:aria-selected="selected ? true : undefined" :aria-selected="selected ? true : undefined"
@change="toggleRowWithCheckbox($event, rowIndex)" @change="toggleRowWithCheckbox($event, rowIndex)"
:pt="pt"
/> />
</template> </template>
<template v-else-if="columnProp('rowReorder')"> <template v-else-if="columnProp('rowReorder')">
<component :is="column.children && column.children.rowreordericon ? column.children.rowreordericon : columnProp('rowReorderIcon') ? 'i' : 'BarsIcon'" :class="['p-datatable-reorderablerow-handle', columnProp('rowReorderIcon')]" /> <component :is="column.children && column.children.rowreordericon ? column.children.rowreordericon : columnProp('rowReorderIcon') ? 'i' : 'BarsIcon'" :class="['p-datatable-reorderablerow-handle', columnProp('rowReorderIcon')]" />
</template> </template>
<template v-else-if="columnProp('expander')"> <template v-else-if="columnProp('expander')">
<button v-ripple class="p-row-toggler p-link" type="button" :aria-expanded="isRowExpanded" :aria-controls="ariaControls" :aria-label="expandButtonAriaLabel" @click="toggleRow"> <button v-ripple class="p-row-toggler p-link" type="button" :aria-expanded="isRowExpanded" :aria-controls="ariaControls" :aria-label="expandButtonAriaLabel" @click="toggleRow" v-bind="ptm('rowToggler')">
<component v-if="column.children && column.children.rowtogglericon" :is="column.children.rowtogglericon" :rowExpanded="isRowExpanded" /> <component v-if="column.children && column.children.rowtogglericon" :is="column.children.rowtogglericon" :rowExpanded="isRowExpanded" />
<template v-else> <template v-else>
<span v-if="isRowExpanded && expandedRowIcon" :class="['p-row-toggler-icon', expandedRowIcon]" /> <span v-if="isRowExpanded && expandedRowIcon" :class="['p-row-toggler-icon', expandedRowIcon]" />
<ChevronDownIcon v-else-if="isRowExpanded && !expandedRowIcon" class="p-row-toggler-icon" /> <ChevronDownIcon v-else-if="isRowExpanded && !expandedRowIcon" class="p-row-toggler-icon" v-bind="ptm('rowTogglerIcon')" />
<span v-else-if="!isRowExpanded && collapsedRowIcon" :class="['p-row-toggler-icon', collapsedRowIcon]" /> <span v-else-if="!isRowExpanded && collapsedRowIcon" :class="['p-row-toggler-icon', collapsedRowIcon]" />
<ChevronRightIcon v-else-if="!isRowExpanded && !collapsedRowIcon" class="p-row-toggler-icon" /> <ChevronRightIcon v-else-if="!isRowExpanded && !collapsedRowIcon" class="p-row-toggler-icon" v-bind="ptm('rowTogglerIcon')" />
</template> </template>
</button> </button>
</template> </template>
<template v-else-if="editMode === 'row' && columnProp('rowEditor')"> <template v-else-if="editMode === 'row' && columnProp('rowEditor')">
<button v-if="!d_editing" v-ripple class="p-row-editor-init p-link" type="button" :aria-label="initButtonAriaLabel" @click="onRowEditInit"> <button v-if="!d_editing" v-ripple class="p-row-editor-init p-link" type="button" :aria-label="initButtonAriaLabel" @click="onRowEditInit" v-bind="ptm('rowEditorInitButton')">
<component :is="(column.children && column.children.roweditoriniticon) || 'PencilIcon'" class="p-row-editor-init-icon" /> <component :is="(column.children && column.children.roweditoriniticon) || 'PencilIcon'" class="p-row-editor-init-icon" v-bind="ptm('rowEditorInitIcon')" />
</button> </button>
<button v-if="d_editing" v-ripple class="p-row-editor-save p-link" type="button" :aria-label="saveButtonAriaLabel" @click="onRowEditSave"> <button v-if="d_editing" v-ripple class="p-row-editor-save p-link" type="button" :aria-label="saveButtonAriaLabel" @click="onRowEditSave" v-bind="ptm('rowEditorEditButton')">
<component :is="(column.children && column.children.roweditorsaveicon) || 'CheckIcon'" class="p-row-editor-save-icon" /> <component :is="(column.children && column.children.roweditorsaveicon) || 'CheckIcon'" class="p-row-editor-save-icon" v-bind="ptm('rowEditorEditIcon')" />
</button> </button>
<button v-if="d_editing" v-ripple class="p-row-editor-cancel p-link" type="button" :aria-label="cancelButtonAriaLabel" @click="onRowEditCancel"> <button v-if="d_editing" v-ripple class="p-row-editor-cancel p-link" type="button" :aria-label="cancelButtonAriaLabel" @click="onRowEditCancel" v-bind="ptm('rowEditorCancelButton')">
<component :is="(column.children && column.children.roweditorcancelicon) || 'TimesIcon'" class="p-row-editor-cancel-icon" /> <component :is="(column.children && column.children.roweditorcancelicon) || 'TimesIcon'" class="p-row-editor-cancel-icon" v-bind="ptm('rowEditorCancelIcon')" />
</button> </button>
</template> </template>
<template v-else>{{ resolveFieldData() }}</template> <template v-else>{{ resolveFieldData() }}</template>
@ -58,6 +59,7 @@
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import BarsIcon from 'primevue/icons/bars'; import BarsIcon from 'primevue/icons/bars';
import CheckIcon from 'primevue/icons/check'; import CheckIcon from 'primevue/icons/check';
import ChevronDownIcon from 'primevue/icons/chevrondown'; import ChevronDownIcon from 'primevue/icons/chevrondown';
@ -72,6 +74,7 @@ import RowRadioButton from './RowRadioButton.vue';
export default { export default {
name: 'BodyCell', name: 'BodyCell',
extends: BaseComponent,
emits: ['cell-edit-init', 'cell-edit-complete', 'cell-edit-cancel', 'row-edit-init', 'row-edit-save', 'row-edit-cancel', 'row-toggle', 'radio-change', 'checkbox-change', 'editing-meta-change'], emits: ['cell-edit-init', 'cell-edit-complete', 'cell-edit-cancel', 'row-edit-init', 'row-edit-save', 'row-edit-cancel', 'row-toggle', 'radio-change', 'checkbox-change', 'editing-meta-change'],
props: { props: {
rowData: { rowData: {

View file

@ -1,6 +1,6 @@
<template> <template>
<div :class="containerClass"> <div :class="containerClass" v-bind="ptm('columnFilter')">
<div v-if="display === 'row'" class="p-fluid p-column-filter-element" v-bind="filterInputProps"> <div v-if="display === 'row'" class="p-fluid p-column-filter-element" v-bind="{ ...filterInputProps, ...ptm('filterInput') }">
<component :is="filterElement" :field="field" :filterModel="filters[field]" :filterCallback="filterCallback" /> <component :is="filterElement" :field="field" :filterModel="filters[field]" :filterCallback="filterCallback" />
</div> </div>
<button <button
@ -15,11 +15,12 @@
:class="{ 'p-column-filter-menu-button-open': overlayVisible, 'p-column-filter-menu-button-active': hasFilter() }" :class="{ 'p-column-filter-menu-button-open': overlayVisible, 'p-column-filter-menu-button-active': hasFilter() }"
@click="toggleMenu()" @click="toggleMenu()"
@keydown="onToggleButtonKeyDown($event)" @keydown="onToggleButtonKeyDown($event)"
v-bind="ptm('filterMenuButton')"
> >
<component :is="filterIconTemplate || 'FilterIcon'" /> <component :is="filterIconTemplate || 'FilterIcon'" />
</button> </button>
<button v-if="showClearButton && display === 'row'" :class="{ 'p-hidden-space': !hasRowFilter() }" type="button" class="p-column-filter-clear-button p-link" @click="clearFilter()"> <button v-if="showClearButton && display === 'row'" :class="{ 'p-hidden-space': !hasRowFilter() }" type="button" class="p-column-filter-clear-button p-link" @click="clearFilter()" v-bind="ptm('headerFilterClearButton')">
<component :is="filterClearIconTemplate || 'FilterSlashIcon'" /> <component :is="filterClearIconTemplate || 'FilterSlashIcon'" v-bind="ptm('filterClearIcon')" />
</button> </button>
<Portal> <Portal>
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave"> <transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
@ -34,10 +35,11 @@
@keydown.escape="hide" @keydown.escape="hide"
@click="onContentClick" @click="onContentClick"
@mousedown="onContentMouseDown" @mousedown="onContentMouseDown"
v-bind="ptm('filterOverlay')"
> >
<component :is="filterHeaderTemplate" :field="field" :filterModel="filters[field]" :filterCallback="filterCallback" /> <component :is="filterHeaderTemplate" :field="field" :filterModel="filters[field]" :filterCallback="filterCallback" />
<template v-if="display === 'row'"> <template v-if="display === 'row'">
<ul class="p-column-filter-row-items"> <ul class="p-column-filter-row-items" v-bind="ptm('filterRowItems')">
<li <li
v-for="(matchMode, i) of matchModes" v-for="(matchMode, i) of matchModes"
:key="matchMode.label" :key="matchMode.label"
@ -47,15 +49,16 @@
@keydown.enter.prevent="onRowMatchModeChange(matchMode.value)" @keydown.enter.prevent="onRowMatchModeChange(matchMode.value)"
:class="{ 'p-highlight': isRowMatchModeSelected(matchMode.value) }" :class="{ 'p-highlight': isRowMatchModeSelected(matchMode.value) }"
:tabindex="i === 0 ? '0' : null" :tabindex="i === 0 ? '0' : null"
v-bind="ptm('filterRowItem')"
> >
{{ matchMode.label }} {{ matchMode.label }}
</li> </li>
<li class="p-column-filter-separator"></li> <li class="p-column-filter-separator" v-bind="ptm('filterSeparator')"></li>
<li class="p-column-filter-row-item" @click="clearFilter()" @keydown="onRowMatchModeKeyDown($event)" @keydown.enter="onRowClearItemClick()">{{ noFilterLabel }}</li> <li class="p-column-filter-row-item" @click="clearFilter()" @keydown="onRowMatchModeKeyDown($event)" @keydown.enter="onRowClearItemClick()" v-bind="ptm('filterRowItem')">{{ noFilterLabel }}</li>
</ul> </ul>
</template> </template>
<template v-else> <template v-else>
<div v-if="isShowOperator" class="p-column-filter-operator"> <div v-if="isShowOperator" class="p-column-filter-operator" v-bind="ptm('filterOperator')">
<CFDropdown <CFDropdown
:options="operatorOptions" :options="operatorOptions"
:modelValue="operator" :modelValue="operator"
@ -64,10 +67,11 @@
optionLabel="label" optionLabel="label"
optionValue="value" optionValue="value"
@update:modelValue="onOperatorChange($event)" @update:modelValue="onOperatorChange($event)"
:pt="ptm('filterOperatorDropdown')"
></CFDropdown> ></CFDropdown>
</div> </div>
<div class="p-column-filter-constraints"> <div class="p-column-filter-constraints" v-bind="ptm('filterConstraints')">
<div v-for="(fieldConstraint, i) of fieldConstraints" :key="i" class="p-column-filter-constraint"> <div v-for="(fieldConstraint, i) of fieldConstraints" :key="i" class="p-column-filter-constraint" v-bind="ptm('filterConstraint')">
<CFDropdown <CFDropdown
v-if="isShowMatchModes" v-if="isShowMatchModes"
:options="matchModes" :options="matchModes"
@ -77,29 +81,37 @@
optionValue="value" optionValue="value"
:aria-label="filterConstraintAriaLabel" :aria-label="filterConstraintAriaLabel"
@update:modelValue="onMenuMatchModeChange($event, i)" @update:modelValue="onMenuMatchModeChange($event, i)"
:pt="ptm('filterMatchModeDropdown')"
></CFDropdown> ></CFDropdown>
<component v-if="display === 'menu'" :is="filterElement" :field="field" :filterModel="fieldConstraint" :filterCallback="filterCallback" /> <component v-if="display === 'menu'" :is="filterElement" :field="field" :filterModel="fieldConstraint" :filterCallback="filterCallback" />
<div> <div v-bind="ptm('filterRemove')">
<CFButton v-if="showRemoveIcon" type="button" class="p-column-filter-remove-button p-button-text p-button-danger p-button-sm" @click="removeConstraint(i)" :label="removeRuleButtonLabel"> <CFButton
v-if="showRemoveIcon"
type="button"
class="p-column-filter-remove-button p-button-text p-button-danger p-button-sm"
@click="removeConstraint(i)"
:label="removeRuleButtonLabel"
:pt="ptm('filterRemoveButton')"
>
<template #icon="iconProps"> <template #icon="iconProps">
<component :is="filterRemoveIconTemplate || 'TrashIcon'" :class="iconProps.class" /> <component :is="filterRemoveIconTemplate || 'TrashIcon'" :class="iconProps.class" v-bind="ptm('filterRemoveButton')['icon']" />
</template> </template>
</CFButton> </CFButton>
</div> </div>
</div> </div>
</div> </div>
<div v-if="isShowAddConstraint" class="p-column-filter-add-rule"> <div v-if="isShowAddConstraint" class="p-column-filter-add-rule" v-bind="ptm('filterAddRule')">
<CFButton type="button" :label="addRuleButtonLabel" iconPos="left" class="p-column-filter-add-button p-button-text p-button-sm" @click="addConstraint()"> <CFButton type="button" :label="addRuleButtonLabel" iconPos="left" class="p-column-filter-add-button p-button-text p-button-sm" @click="addConstraint()" :pt="ptm('filterAddRuleButton')">
<template #icon="iconProps"> <template #icon="iconProps">
<component :is="filterAddIconTemplate || 'PlusIcon'" :class="iconProps.class" /> <component :is="filterAddIconTemplate || 'PlusIcon'" :class="iconProps.class" v-bind="ptm('filterAddRuleButton')['icon']" />
</template> </template>
</CFButton> </CFButton>
</div> </div>
<div class="p-column-filter-buttonbar"> <div class="p-column-filter-buttonbar" v-bind="ptm('filterButtonbar')">
<CFButton v-if="!filterClearTemplate && showClearButton" type="button" class="p-button-outlined p-button-sm" :label="clearButtonLabel" @click="clearFilter"></CFButton> <CFButton v-if="!filterClearTemplate && showClearButton" type="button" class="p-button-outlined p-button-sm" :label="clearButtonLabel" @click="clearFilter" :pt="ptm('filterClearButton')"></CFButton>
<component v-else :is="filterClearTemplate" :field="field" :filterModel="filters[field]" :filterCallback="clearFilter" /> <component v-else :is="filterClearTemplate" :field="field" :filterModel="filters[field]" :filterCallback="clearFilter" />
<template v-if="showApplyButton"> <template v-if="showApplyButton">
<CFButton v-if="!filterApplyTemplate" type="button" class="p-button-sm" :label="applyButtonLabel" @click="applyFilter()"></CFButton> <CFButton v-if="!filterApplyTemplate" type="button" class="p-button-sm" :label="applyButtonLabel" @click="applyFilter()" v-bind="ptm('filterApplyButton')"></CFButton>
<component v-else :is="filterApplyTemplate" :field="field" :filterModel="filters[field]" :filterCallback="applyFilter" /> <component v-else :is="filterApplyTemplate" :field="field" :filterModel="filters[field]" :filterCallback="applyFilter" />
</template> </template>
</div> </div>
@ -113,6 +125,7 @@
<script> <script>
import { FilterOperator } from 'primevue/api'; import { FilterOperator } from 'primevue/api';
import BaseComponent from 'primevue/basecomponent';
import Button from 'primevue/button'; import Button from 'primevue/button';
import Dropdown from 'primevue/dropdown'; import Dropdown from 'primevue/dropdown';
import FocusTrap from 'primevue/focustrap'; import FocusTrap from 'primevue/focustrap';
@ -126,6 +139,7 @@ import { ConnectedOverlayScrollHandler, DomHandler, UniqueComponentId, ZIndexUti
export default { export default {
name: 'ColumnFilter', name: 'ColumnFilter',
extends: BaseComponent,
emits: ['filter-change', 'filter-apply', 'operator-change', 'matchmode-change', 'constraint-add', 'constraint-remove', 'filter-clear', 'apply-click'], emits: ['filter-change', 'filter-apply', 'operator-change', 'matchmode-change', 'constraint-add', 'constraint-remove', 'filter-clear', 'apply-click'],
props: { props: {
field: { field: {

View file

@ -8,8 +8,22 @@
* *
*/ */
import { InputHTMLAttributes, TableHTMLAttributes, VNode } from 'vue'; import { InputHTMLAttributes, TableHTMLAttributes, VNode } from 'vue';
import { ButtonPassThroughOptionType } from '../button';
import { DropdownPassThroughOptionType } from '../dropdown';
import { PaginatorPassThroughOptionType } from '../paginator';
import { ClassComponent, GlobalComponentConstructor, Nullable } from '../ts-helpers'; import { ClassComponent, GlobalComponentConstructor, Nullable } from '../ts-helpers';
import { VirtualScrollerProps } from '../virtualscroller'; import { VirtualScrollerPassThroughOptionType, VirtualScrollerProps } from '../virtualscroller';
export declare type DataTablePassThroughOptionType = DataTablePassThroughAttributes | ((options: DataTablePassThroughMethodOptions) => DataTablePassThroughAttributes) | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface DataTablePassThroughMethodOptions {
props: DataTableProps;
state: DataTableState;
context: DataTableContext;
}
/** /**
* Custom datatable export metadata. * Custom datatable export metadata.
@ -521,6 +535,433 @@ export interface DataTableStateEvent {
selectionKeys: any[]; selectionKeys: any[];
} }
/**
* Custom passthrough(pt) options.
* @see {@link DataTableProps.pt}
*/
export interface DataTablePassThroughOptions {
/**
* Uses to pass attributes to the root's DOM element.
*/
root?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the loading overlay's DOM element.
*/
loadingOverlay?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the loadingIcon's DOM element.
*/
loadingIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header's DOM element.
*/
header?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the Paginator component.
* @see {@link PaginatorPassThroughOptionType}
*/
paginator?: PaginatorPassThroughOptionType;
/**
* Uses to pass attributes to the wrapper's DOM element.
*/
wrapper?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the VirtualScroller component.
* @see {@link VirtualScrollerPassThroughOptionType}
*/
virtualScroller?: VirtualScrollerPassThroughOptionType;
/**
* Uses to pass attributes to the table's DOM element.
*/
table?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the virtual scroller spacer's DOM element.
*/
virtualScrollerSpacer?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the footer's DOM element.
*/
footer?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the thead's DOM element.
*/
thead?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header row's DOM element.
*/
headerRow?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header cell's DOM element.
*/
headerCell?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the column resizer's DOM element.
*/
columnResizer?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header content's DOM element.
*/
headerContent?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header title's DOM element.
*/
headerTitle?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the sort's DOM element.
*/
sort?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the sort badge's DOM element.
*/
sortBadge?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header checkbox's DOM element.
*/
headerCheckbox?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the header checkbox icon's DOM element.
*/
headerCheckboxIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the column filter's DOM element.
*/
columnFilter?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filter input's DOM element.
*/
filterInput?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterMenuButton's DOM element.
*/
filterMenuButton?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the headerFilterClearButton's DOM element.
*/
headerFilterClearButton?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterClearIcon's DOM element.
*/
filterClearIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterOverlay's DOM element.
*/
filterOverlay?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterRowItems's DOM element.
*/
filterRowItems?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterRowItem's DOM element.
*/
filterRowItem?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterSeparator's DOM element.
*/
filterSeparator?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterOperator's DOM element.
*/
filterOperator?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the Dropdown component.
* @see {@link DropdownPassThroughOptionType}
*/
filterOperatorDropdown?: DropdownPassThroughOptionType;
/**
* Uses to pass attributes to the filterConstraints's DOM element.
*/
filterConstraints?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the filterConstraint's DOM element.
*/
filterConstraint?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the Dropdown component.
* @see {@link DropdownPassThroughOptionType}
*/
filterMatchModeDropdown?: DropdownPassThroughOptionType;
/**
* Uses to pass attributes to the filterRemoveButtonContainer's DOM element.
*/
filterRemove?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the Button component.
* @see {@link ButtonPassThroughOptionType}
*/
filterRemoveButton?: ButtonPassThroughOptionType;
/**
* Uses to pass attributes to the filterAddRule's DOM element.
*/
filterAddRule?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the Button component.
* @see {@link ButtonPassThroughOptionType}
*/
filterAddRuleButton?: ButtonPassThroughOptionType;
/**
* Uses to pass attributes to the filterButtonbar's DOM element.
*/
filterButtonbar?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the Button component.
* @see {@link ButtonPassThroughOptionType}
*/
filterClearButton?: ButtonPassThroughOptionType;
/**
* Uses to pass attributes to the Button component.
* @see {@link ButtonPassThroughOptionType}
*/
filterApplyButton?: ButtonPassThroughOptionType;
/**
* Uses to pass attributes to the tbody's DOM element.
*/
tbody?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowgroupHeader's DOM element.
*/
rowgroupHeader?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the bodyCell's DOM element.
*/
bodyCell?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowGroupToggler's DOM element.
*/
rowGroupToggler?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowGroupTogglerIcon's DOM element.
*/
rowGroupTogglerIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the row's DOM element.
*/
row?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowExpansion's DOM element.
*/
rowExpansion?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowgroupFooter's DOM element.
*/
rowgroupFooter?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the emptyMessage's DOM element.
*/
emptyMessage?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the columnTitle's DOM element.
*/
columnTitle?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the radiobuttonWrapper's DOM element.
*/
radiobuttonWrapper?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the radiobutton's DOM element.
*/
radiobutton?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the radiobuttonIcon's DOM element.
*/
radiobuttonIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the checkboxWrapper's DOM element.
*/
checkboxWrapper?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the checkbox's DOM element.
*/
checkbox?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the checkboxIcon's DOM element.
*/
checkboxIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowToggler's DOM element.
*/
rowToggler?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowTogglerIcon's DOM element.
*/
rowTogglerIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowEditorInitButton's DOM element.
*/
rowEditorInitButton?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowEditorInitIcon's DOM element.
*/
rowEditorInitIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowEditorEditButton's DOM element.
*/
rowEditorEditButton?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowEditorEditIcon's DOM element.
*/
rowEditorEditIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowEditorCancelButton's DOM element.
*/
rowEditorCancelButton?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the rowEditorCancelIcon's DOM element.
*/
rowEditorCancelIcon?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the tfoot's DOM element.
*/
tfoot?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the footerRow's DOM element.
*/
footerRow?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the footerCell's DOM element.
*/
footerCell?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the resizeHelper's DOM element.
*/
resizeHelper?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the reorderIndicatorUp's DOM element.
*/
reorderIndicatorUp?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the reorderIndicatorDown's DOM element.
*/
reorderIndicatorDown?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the hidden input wrapper's DOM element.
*/
hiddenHeaderInputWrapper?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the hidden input's DOM element.
*/
hiddenHeaderInput?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the hidden input wrapper's DOM element.
*/
hiddenInputWrapper?: DataTablePassThroughOptionType;
/**
* Uses to pass attributes to the hidden input's DOM element.
*/
hiddenInput?: DataTablePassThroughOptionType;
}
/**
* Custom passthrough attributes for each DOM elements
*/
export interface DataTablePassThroughAttributes {
[key: string]: any;
}
/**
* Defines current inline state in DataTable component.
*/
export interface DataTableState {
/**
* Current index of first record as a number.
*/
d_first: number;
/**
* Current number of rows to display in new page as a number.
*/
d_rows: number;
/**
* Current sort field.
*/
d_sortField: string | ((item: any) => string) | undefined;
/**
* Current order to sort the data by default.
*/
d_sortOrder: number;
/**
* Current sortmeta objects to sort the data.
*/
d_multiSortMeta: DataTableSortMeta[];
/**
* Current group sortmeta objects to sort the data.
*/
d_groupRowsSortMeta: DataTableSortMeta;
/**
* Current keys of selected rows.
*/
d_selectionKeys: any[];
/**
* Current keys of rows in expanded state.
*/
d_expandedRowKeys: any[];
/**
* Current order of the columns.
*/
d_columnOrder: string[];
/**
* Current keys of editing rows.
*/
d_editingRowKeys: any;
/**
* Current editing meta data.
*/
d_editingMeta: object;
/**
* Current filters object.
*/
d_filters: DataTableFilterMeta;
/**
* Current editing as a boolean.
* @defaultValue false
*/
d_editing: boolean;
/**
* Current style of the body cell.
*/
styleObject: object;
/**
* Current filter overlay visible as a boolean.
*/
overlayVisible: boolean;
/**
* Current filter match mode.
*/
defaultMatchMode: string;
/**
* Current filter operator.
*/
defaultOperator: string;
/**
* Current focused state as a boolean.
* @defaultValue false
*/
focused: boolean;
/**
* Current style of the rowgroup header.
*/
rowGroupHeaderStyleObject: object;
}
/**
* Defines current options in DataTable component.
*/
export interface DataTableContext {
/**
* Current checked state of row as a boolean.
* @defaultValue false
*/
checked: boolean;
/**
* Current focused state of row as a boolean.
* @defaultValue false
*/
focused: boolean;
/**
* Current disabled state of row as a boolean.
* @defaultValue false
*/
disabled: boolean;
}
/** /**
* Defines valid properties in DataTable component. * Defines valid properties in DataTable component.
*/ */
@ -829,6 +1270,11 @@ export interface DataTableProps {
* Uses to pass all properties of the HTMLInputElement to the focusable filter input element inside the component. * Uses to pass all properties of the HTMLInputElement to the focusable filter input element inside the component.
*/ */
filterInputProps?: InputHTMLAttributes | undefined; filterInputProps?: InputHTMLAttributes | undefined;
/**
* Uses to pass attributes to DOM elements inside the component.
* @type {DataTablePassThroughOptions}
*/
pt?: DataTablePassThroughOptions;
} }
/** /**

View file

@ -1,15 +1,15 @@
<template> <template>
<div :class="containerClass" data-scrollselectors=".p-datatable-wrapper"> <div :class="containerClass" data-scrollselectors=".p-datatable-wrapper" v-bind="ptm('root')">
<slot></slot> <slot></slot>
<div v-if="loading" class="p-datatable-loading-overlay p-component-overlay"> <div v-if="loading" class="p-datatable-loading-overlay p-component-overlay" v-bind="ptm('loadingOverlay')">
<slot v-if="$slots.loading" name="loading"></slot> <slot v-if="$slots.loading" name="loading"></slot>
<template v-else> <template v-else>
<component v-if="$slots.loadingicon" :is="$slots.loadingicon" class="p-datatable-loading-icon" /> <component v-if="$slots.loadingicon" :is="$slots.loadingicon" class="p-datatable-loading-icon" />
<i v-else-if="loadingIcon" :class="['p-datatable-loading-icon pi-spin', loadingIcon]" /> <i v-else-if="loadingIcon" :class="['p-datatable-loading-icon pi-spin', loadingIcon]" v-bind="ptm('loadingIcon')" />
<SpinnerIcon v-else spin class="p-datatable-loading-icon" /> <SpinnerIcon v-else spin class="p-datatable-loading-icon" v-bind="ptm('loadingIcon')" />
</template> </template>
</div> </div>
<div v-if="$slots.header" class="p-datatable-header"> <div v-if="$slots.header" class="p-datatable-header" v-bind="ptm('header')">
<slot name="header"></slot> <slot name="header"></slot>
</div> </div>
<DTPaginator <DTPaginator
@ -24,6 +24,7 @@
class="p-paginator-top" class="p-paginator-top"
@page="onPage($event)" @page="onPage($event)"
:alwaysShow="alwaysShowPaginator" :alwaysShow="alwaysShowPaginator"
:pt="ptm('paginator')"
> >
<template v-if="$slots.paginatorstart" #start> <template v-if="$slots.paginatorstart" #start>
<slot name="paginatorstart"></slot> <slot name="paginatorstart"></slot>
@ -44,10 +45,10 @@
<slot name="paginatorlastpagelinkicon"></slot> <slot name="paginatorlastpagelinkicon"></slot>
</template> </template>
</DTPaginator> </DTPaginator>
<div class="p-datatable-wrapper" :style="{ maxHeight: virtualScrollerDisabled ? scrollHeight : '' }"> <div class="p-datatable-wrapper" :style="{ maxHeight: virtualScrollerDisabled ? scrollHeight : '' }" v-bind="ptm('wrapper')">
<DTVirtualScroller <DTVirtualScroller
ref="virtualScroller" ref="virtualScroller"
v-bind="virtualScrollerOptions" v-bind="{ ...virtualScrollerOptions, ...ptm('virtualScroller') }"
:items="processedData" :items="processedData"
:columns="columns" :columns="columns"
:style="scrollHeight !== 'flex' ? { height: scrollHeight } : undefined" :style="scrollHeight !== 'flex' ? { height: scrollHeight } : undefined"
@ -59,7 +60,7 @@
:showSpacer="false" :showSpacer="false"
> >
<template #content="slotProps"> <template #content="slotProps">
<table ref="table" role="table" :class="tableStyleClass" :style="[tableStyle, slotProps.spacerStyle]" v-bind="tableProps"> <table ref="table" role="table" :class="tableStyleClass" :style="[tableStyle, slotProps.spacerStyle]" v-bind="{ ...tableProps, ...ptm('table') }">
<DTTableHeader <DTTableHeader
:columnGroup="headerColumnGroup" :columnGroup="headerColumnGroup"
:columns="slotProps.columns" :columns="slotProps.columns"
@ -89,6 +90,7 @@
@column-drop="onColumnHeaderDrop($event)" @column-drop="onColumnHeaderDrop($event)"
@column-resizestart="onColumnResizeStart($event)" @column-resizestart="onColumnResizeStart($event)"
@checkbox-change="toggleRowsWithCheckbox($event)" @checkbox-change="toggleRowsWithCheckbox($event)"
:pt="pt"
/> />
<DTTableBody <DTTableBody
v-if="frozenValue" v-if="frozenValue"
@ -201,14 +203,20 @@
@row-edit-cancel="onRowEditCancel($event)" @row-edit-cancel="onRowEditCancel($event)"
:editingMeta="d_editingMeta" :editingMeta="d_editingMeta"
@editing-meta-change="onEditingMetaChange" @editing-meta-change="onEditingMetaChange"
:pt="pt"
/> />
<tbody v-if="hasSpacerStyle(slotProps.spacerStyle)" :style="{ height: `calc(${slotProps.spacerStyle.height} - ${slotProps.rows.length * slotProps.itemSize}px)` }" class="p-datatable-virtualscroller-spacer"></tbody> <tbody
<DTTableFooter :columnGroup="footerColumnGroup" :columns="slotProps.columns" /> v-if="hasSpacerStyle(slotProps.spacerStyle)"
:style="{ height: `calc(${slotProps.spacerStyle.height} - ${slotProps.rows.length * slotProps.itemSize}px)` }"
class="p-datatable-virtualscroller-spacer"
v-bind="ptm('virtualScrollerSpacer')"
></tbody>
<DTTableFooter :columnGroup="footerColumnGroup" :columns="slotProps.columns" :pt="pt" />
</table> </table>
</template> </template>
</DTVirtualScroller> </DTVirtualScroller>
</div> </div>
<div v-if="$slots.footer" class="p-datatable-footer"> <div v-if="$slots.footer" class="p-datatable-footer" v-bind="ptm('footer')">
<slot name="footer"></slot> <slot name="footer"></slot>
</div> </div>
<DTPaginator <DTPaginator
@ -223,6 +231,7 @@
class="p-paginator-bottom" class="p-paginator-bottom"
@page="onPage($event)" @page="onPage($event)"
:alwaysShow="alwaysShowPaginator" :alwaysShow="alwaysShowPaginator"
v-bind="ptm('paginator')"
> >
<template v-if="$slots.paginatorstart" #start> <template v-if="$slots.paginatorstart" #start>
<slot name="paginatorstart"></slot> <slot name="paginatorstart"></slot>
@ -243,11 +252,11 @@
<slot name="paginatorlastpagelinkicon"></slot> <slot name="paginatorlastpagelinkicon"></slot>
</template> </template>
</DTPaginator> </DTPaginator>
<div ref="resizeHelper" class="p-column-resizer-helper" style="display: none"></div> <div ref="resizeHelper" class="p-column-resizer-helper" style="display: none" v-bind="ptm('resizeHelper')"></div>
<span v-if="reorderableColumns" ref="reorderIndicatorUp" class="p-datatable-reorder-indicator-up" style="position: absolute; display: none"> <span v-if="reorderableColumns" ref="reorderIndicatorUp" class="p-datatable-reorder-indicator-up" style="position: absolute; display: none" v-bind="ptm('reorderIndicatorUp')">
<component :is="$slots.reorderindicatorupicon || 'ArrowDownIcon'" /> <component :is="$slots.reorderindicatorupicon || 'ArrowDownIcon'" />
</span> </span>
<span v-if="reorderableColumns" ref="reorderIndicatorDown" class="p-datatable-reorder-indicator-down" style="position: absolute; display: none"> <span v-if="reorderableColumns" ref="reorderIndicatorDown" class="p-datatable-reorder-indicator-down" style="position: absolute; display: none" v-bind="ptm('reorderIndicatorDown')">
<component :is="$slots.reorderindicatordownicon || 'ArrowUpIcon'" /> <component :is="$slots.reorderindicatordownicon || 'ArrowUpIcon'" />
</span> </span>
</div> </div>
@ -255,6 +264,7 @@
<script> <script>
import { FilterMatchMode, FilterOperator, FilterService } from 'primevue/api'; import { FilterMatchMode, FilterOperator, FilterService } from 'primevue/api';
import BaseComponent from 'primevue/basecomponent';
import ArrowDownIcon from 'primevue/icons/arrowdown'; import ArrowDownIcon from 'primevue/icons/arrowdown';
import ArrowUpIcon from 'primevue/icons/arrowup'; import ArrowUpIcon from 'primevue/icons/arrowup';
import SpinnerIcon from 'primevue/icons/spinner'; import SpinnerIcon from 'primevue/icons/spinner';
@ -267,6 +277,7 @@ import TableHeader from './TableHeader.vue';
export default { export default {
name: 'DataTable', name: 'DataTable',
extends: BaseComponent,
emits: [ emits: [
'value-change', 'value-change',
'update:first', 'update:first',

View file

@ -1,15 +1,17 @@
<template> <template>
<td :style="containerStyle" :class="containerClass" role="cell" :colspan="columnProp('colspan')" :rowspan="columnProp('rowspan')"> <td :style="containerStyle" :class="containerClass" role="cell" :colspan="columnProp('colspan')" :rowspan="columnProp('rowspan')" v-bind="ptm('footerCell')">
<component v-if="column.children && column.children.footer" :is="column.children.footer" :column="column" /> <component v-if="column.children && column.children.footer" :is="column.children.footer" :column="column" />
{{ columnProp('footer') }} {{ columnProp('footer') }}
</td> </td>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import { DomHandler, ObjectUtils } from 'primevue/utils'; import { DomHandler, ObjectUtils } from 'primevue/utils';
export default { export default {
name: 'FooterCell', name: 'FooterCell',
extends: BaseComponent,
props: { props: {
column: { column: {
type: Object, type: Object,

View file

@ -14,16 +14,24 @@
@dragover="onDragOver" @dragover="onDragOver"
@dragleave="onDragLeave" @dragleave="onDragLeave"
@drop="onDrop" @drop="onDrop"
v-bind="ptm('headerCell')"
> >
<span v-if="resizableColumns && !columnProp('frozen')" class="p-column-resizer" @mousedown="onResizeStart"></span> <span v-if="resizableColumns && !columnProp('frozen')" class="p-column-resizer" @mousedown="onResizeStart" v-bind="ptm('columnResizer')"></span>
<div class="p-column-header-content"> <div class="p-column-header-content" v-bind="ptm('headerContent')">
<component v-if="column.children && column.children.header" :is="column.children.header" :column="column" /> <component v-if="column.children && column.children.header" :is="column.children.header" :column="column" />
<span v-if="columnProp('header')" class="p-column-title">{{ columnProp('header') }}</span> <span v-if="columnProp('header')" class="p-column-title" v-bind="ptm('headerTitle')">{{ columnProp('header') }}</span>
<span v-if="columnProp('sortable')"> <span v-if="columnProp('sortable')" v-bind="ptm('sort')">
<component :is="(column.children && column.children.sorticon) || sortableColumnIcon" :sorted="sortState.sorted" :sortOrder="sortState.sortOrder" class="p-sortable-column-icon" /> <component :is="(column.children && column.children.sorticon) || sortableColumnIcon" :sorted="sortState.sorted" :sortOrder="sortState.sortOrder" class="p-sortable-column-icon" />
</span> </span>
<span v-if="isMultiSorted()" class="p-sortable-column-badge">{{ getBadgeValue() }}</span> <span v-if="isMultiSorted()" class="p-sortable-column-badge" v-bind="ptm('sortBadge')">{{ getBadgeValue() }}</span>
<DTHeaderCheckbox v-if="columnProp('selectionMode') === 'multiple' && filterDisplay !== 'row'" :checked="allRowsSelected" @change="onHeaderCheckboxChange" :disabled="empty" :headerCheckboxIconTemplate="headerCheckboxIconTemplate" /> <DTHeaderCheckbox
v-if="columnProp('selectionMode') === 'multiple' && filterDisplay !== 'row'"
:checked="allRowsSelected"
@change="onHeaderCheckboxChange"
:disabled="empty"
:headerCheckboxIconTemplate="headerCheckboxIconTemplate"
:pt="pt"
/>
<DTColumnFilter <DTColumnFilter
v-if="filterDisplay === 'menu' && column.children && column.children.filter" v-if="filterDisplay === 'menu' && column.children && column.children.filter"
:field="columnProp('filterField') || columnProp('field')" :field="columnProp('filterField') || columnProp('field')"
@ -58,12 +66,14 @@
@constraint-add="$emit('constraint-add', $event)" @constraint-add="$emit('constraint-add', $event)"
@constraint-remove="$emit('constraint-remove', $event)" @constraint-remove="$emit('constraint-remove', $event)"
@apply-click="$emit('apply-click', $event)" @apply-click="$emit('apply-click', $event)"
:pt="pt"
/> />
</div> </div>
</th> </th>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import SortAltIcon from 'primevue/icons/sortalt'; import SortAltIcon from 'primevue/icons/sortalt';
import SortAmountDownIcon from 'primevue/icons/sortamountdown'; import SortAmountDownIcon from 'primevue/icons/sortamountdown';
import SortAmountUpAltIcon from 'primevue/icons/sortamountupalt'; import SortAmountUpAltIcon from 'primevue/icons/sortamountupalt';
@ -73,6 +83,7 @@ import HeaderCheckbox from './HeaderCheckbox.vue';
export default { export default {
name: 'HeaderCell', name: 'HeaderCell',
extends: BaseComponent,
emits: [ emits: [
'column-click', 'column-click',
'column-mousedown', 'column-mousedown',

View file

@ -1,21 +1,23 @@
<template> <template>
<div :class="['p-checkbox p-component', { 'p-checkbox-focused': focused, 'p-disabled': disabled }]" @click="onClick" @keydown.space.prevent="onClick"> <div :class="['p-checkbox p-component', { 'p-checkbox-focused': focused, 'p-disabled': disabled }]" @click="onClick" @keydown.space.prevent="onClick" v-bind="ptm('headerCheckbox')">
<div class="p-hidden-accessible"> <div class="p-hidden-accessible" v-bind="ptm('hiddenHeaderInputWrapper')">
<input ref="input" type="checkbox" :checked="checked" :disabled="disabled" :tabindex="disabled ? null : '0'" :aria-label="headerCheckboxAriaLabel" @focus="onFocus($event)" @blur="onBlur($event)" /> <input ref="input" type="checkbox" :checked="checked" :disabled="disabled" :tabindex="disabled ? null : '0'" :aria-label="headerCheckboxAriaLabel" @focus="onFocus($event)" @blur="onBlur($event)" v-bind="ptm('hiddenHeaderInput')" />
</div> </div>
<div ref="box" :class="['p-checkbox-box p-component', { 'p-highlight': checked, 'p-disabled': disabled, 'p-focus': focused }]"> <div ref="box" :class="['p-checkbox-box p-component', { 'p-highlight': checked, 'p-disabled': disabled, 'p-focus': focused }]" v-bind="getPTOptions('checkbox')">
<component v-if="headerCheckboxIconTemplate" :is="headerCheckboxIconTemplate" :checked="checked" class="p-checkbox-icon" /> <component v-if="headerCheckboxIconTemplate" :is="headerCheckboxIconTemplate" :checked="checked" class="p-checkbox-icon" />
<CheckIcon v-else class="p-checkbox-icon" /> <CheckIcon v-else class="p-checkbox-icon" v-bind="getPTOptions('headerCheckboxIcon')" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import CheckIcon from 'primevue/icons/check'; import CheckIcon from 'primevue/icons/check';
import { DomHandler } from 'primevue/utils'; import { DomHandler } from 'primevue/utils';
export default { export default {
name: 'HeaderCheckbox', name: 'HeaderCheckbox',
extends: BaseComponent,
emits: ['change'], emits: ['change'],
props: { props: {
checked: null, checked: null,
@ -31,6 +33,15 @@ export default {
}; };
}, },
methods: { methods: {
getPTOptions(key) {
return this.ptm(key, {
context: {
checked: this.checked,
focused: this.focused,
disabled: this.disabled
}
});
},
onClick(event) { onClick(event) {
if (!this.disabled) { if (!this.disabled) {
this.$emit('change', { this.$emit('change', {

View file

@ -1,21 +1,34 @@
<template> <template>
<div :class="['p-checkbox p-component', { 'p-checkbox-focused': focused }]" @click="onClick"> <div :class="['p-checkbox p-component', { 'p-checkbox-focused': focused }]" @click="onClick" v-bind="ptm('checkboxWrapper')">
<div class="p-hidden-accessible"> <div class="p-hidden-accessible" v-bind="ptm('hiddenInputWrapper')">
<input ref="input" type="checkbox" :checked="checked" :disabled="$attrs.disabled" :tabindex="$attrs.disabled ? null : '0'" :aria-label="checkboxAriaLabel" @focus="onFocus($event)" @blur="onBlur($event)" @keydown="onKeydown" /> <input
ref="input"
type="checkbox"
:checked="checked"
:disabled="$attrs.disabled"
:tabindex="$attrs.disabled ? null : '0'"
:aria-label="checkboxAriaLabel"
@focus="onFocus($event)"
@blur="onBlur($event)"
@keydown="onKeydown"
v-bind="ptm('hiddenInput')"
/>
</div> </div>
<div ref="box" :class="['p-checkbox-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]"> <div ref="box" :class="['p-checkbox-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]" v-bind="getPTOptions('checkbox')">
<component v-if="rowCheckboxIconTemplate" :is="rowCheckboxIconTemplate" :checked="checked" class="p-checkbox-icon" /> <component v-if="rowCheckboxIconTemplate" :is="rowCheckboxIconTemplate" :checked="checked" class="p-checkbox-icon" />
<CheckIcon v-else class="p-checkbox-icon" /> <CheckIcon v-else class="p-checkbox-icon" v-bind="getPTOptions('checkboxIcon')" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import CheckIcon from 'primevue/icons/check'; import CheckIcon from 'primevue/icons/check';
import { DomHandler } from 'primevue/utils'; import { DomHandler } from 'primevue/utils';
export default { export default {
name: 'RowCheckbox', name: 'RowCheckbox',
extends: BaseComponent,
emits: ['change'], emits: ['change'],
props: { props: {
value: null, value: null,
@ -31,6 +44,15 @@ export default {
}; };
}, },
methods: { methods: {
getPTOptions(key) {
return this.ptm(key, {
context: {
checked: this.checked,
focused: this.focused,
disabled: this.$attrs.disabled
}
});
},
onClick(event) { onClick(event) {
if (!this.$attrs.disabled) { if (!this.$attrs.disabled) {
this.$emit('change', { this.$emit('change', {

View file

@ -1,19 +1,21 @@
<template> <template>
<div :class="['p-radiobutton p-component', { 'p-radiobutton-focused': focused }]" @click="onClick"> <div :class="['p-radiobutton p-component', { 'p-radiobutton-focused': focused }]" @click="onClick" v-bind="ptm('radiobuttonWrapper')">
<div class="p-hidden-accessible"> <div class="p-hidden-accessible" v-bind="ptm('hiddenInputWrapper')">
<input ref="input" type="radio" :checked="checked" :disabled="$attrs.disabled" :name="name" tabindex="0" @focus="onFocus($event)" @blur="onBlur($event)" @keydown.space.prevent="onClick" /> <input ref="input" type="radio" :checked="checked" :disabled="$attrs.disabled" :name="name" tabindex="0" @focus="onFocus($event)" @blur="onBlur($event)" @keydown.space.prevent="onClick" v-bind="ptm('hiddenInput')" />
</div> </div>
<div ref="box" :class="['p-radiobutton-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]"> <div ref="box" :class="['p-radiobutton-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]" v-bind="ptm('radiobutton')">
<div class="p-radiobutton-icon"></div> <div class="p-radiobutton-icon" v-bind="ptm('radiobuttonIcon')"></div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import { DomHandler } from 'primevue/utils'; import { DomHandler } from 'primevue/utils';
export default { export default {
name: 'RowRadioButton', name: 'RowRadioButton',
extends: BaseComponent,
inheritAttrs: false, inheritAttrs: false,
emits: ['change'], emits: ['change'],
props: { props: {
@ -27,6 +29,15 @@ export default {
}; };
}, },
methods: { methods: {
getPTOptions(key) {
return this.ptm(key, {
context: {
checked: this.checked,
focused: this.focused,
disabled: this.$attrs.disabled
}
});
},
onClick(event) { onClick(event) {
if (!this.disabled) { if (!this.disabled) {
if (!this.checked) { if (!this.checked) {

View file

@ -1,5 +1,5 @@
<template> <template>
<tbody :ref="bodyRef" class="p-datatable-tbody" role="rowgroup" :style="bodyStyle"> <tbody :ref="bodyRef" class="p-datatable-tbody" role="rowgroup" :style="bodyStyle" v-bind="ptm('tbody')">
<template v-if="!empty"> <template v-if="!empty">
<template v-for="(rowData, index) of value"> <template v-for="(rowData, index) of value">
<tr <tr
@ -8,15 +8,16 @@
class="p-rowgroup-header" class="p-rowgroup-header"
:style="rowGroupHeaderStyle" :style="rowGroupHeaderStyle"
role="row" role="row"
v-bind="ptm('rowgroupHeader')"
> >
<td :colspan="columnsLength - 1"> <td :colspan="columnsLength - 1" v-bind="ptm('bodyCell')">
<button v-if="expandableRowGroups" class="p-row-toggler p-link" @click="onRowGroupToggle($event, rowData)" type="button"> <button v-if="expandableRowGroups" class="p-row-toggler p-link" @click="onRowGroupToggle($event, rowData)" type="button" v-bind="ptm('rowGroupToggler')">
<component v-if="templates['rowgrouptogglericon']" :is="templates['rowgrouptogglericon']" :expanded="isRowGroupExpanded(rowData)" /> <component v-if="templates['rowgrouptogglericon']" :is="templates['rowgrouptogglericon']" :expanded="isRowGroupExpanded(rowData)" />
<template v-else> <template v-else>
<span v-if="isRowGroupExpanded(rowData) && expandedRowIcon" :class="['p-row-toggler-icon', expandedRowIcon]" /> <span v-if="isRowGroupExpanded(rowData) && expandedRowIcon" :class="['p-row-toggler-icon', expandedRowIcon]" />
<ChevronDownIcon v-else-if="isRowGroupExpanded(rowData) && !expandedRowIcon" class="p-row-toggler-icon" /> <ChevronDownIcon v-else-if="isRowGroupExpanded(rowData) && !expandedRowIcon" class="p-row-toggler-icon" v-bind="ptm('rowGroupTogglerIcon')" />
<span v-else-if="!isRowGroupExpanded(rowData) && collapsedRowIcon" :class="['p-row-toggler-icon', collapsedRowIcon]" /> <span v-else-if="!isRowGroupExpanded(rowData) && collapsedRowIcon" :class="['p-row-toggler-icon', collapsedRowIcon]" />
<ChevronRightIcon v-else-if="!isRowGroupExpanded(rowData) && !collapsedRowIcon" class="p-row-toggler-icon" /> <ChevronRightIcon v-else-if="!isRowGroupExpanded(rowData) && !collapsedRowIcon" class="p-row-toggler-icon" v-bind="ptm('rowGroupTogglerIcon')" />
</template> </template>
</button> </button>
<component :is="templates['groupheader']" :data="rowData" :index="getRowIndex(index)" /> <component :is="templates['groupheader']" :data="rowData" :index="getRowIndex(index)" />
@ -41,6 +42,7 @@
@dragleave="onRowDragLeave($event)" @dragleave="onRowDragLeave($event)"
@dragend="onRowDragEnd($event)" @dragend="onRowDragEnd($event)"
@drop="onRowDrop($event)" @drop="onRowDrop($event)"
v-bind="ptm('row')"
> >
<template v-for="(col, i) of columns"> <template v-for="(col, i) of columns">
<DTBodyCell <DTBodyCell
@ -73,22 +75,36 @@
@row-edit-save="onRowEditSave($event)" @row-edit-save="onRowEditSave($event)"
@row-edit-cancel="onRowEditCancel($event)" @row-edit-cancel="onRowEditCancel($event)"
@editing-meta-change="onEditingMetaChange" @editing-meta-change="onEditingMetaChange"
:pt="pt"
/> />
</template> </template>
</tr> </tr>
<tr v-if="templates['expansion'] && expandedRows && isRowExpanded(rowData)" :key="getRowKey(rowData, getRowIndex(index)) + '_expansion'" :id="expandedRowId + '_' + index + '_expansion'" class="p-datatable-row-expansion" role="row"> <tr
v-if="templates['expansion'] && expandedRows && isRowExpanded(rowData)"
:key="getRowKey(rowData, getRowIndex(index)) + '_expansion'"
:id="expandedRowId + '_' + index + '_expansion'"
class="p-datatable-row-expansion"
role="row"
v-bind="ptm('rowExpansion')"
>
<td :colspan="columnsLength"> <td :colspan="columnsLength">
<component :is="templates['expansion']" :data="rowData" :index="getRowIndex(index)" /> <component :is="templates['expansion']" :data="rowData" :index="getRowIndex(index)" />
</td> </td>
</tr> </tr>
<tr v-if="templates['groupfooter'] && rowGroupMode === 'subheader' && shouldRenderRowGroupFooter(value, rowData, getRowIndex(index))" :key="getRowKey(rowData, getRowIndex(index)) + '_subfooter'" class="p-rowgroup-footer" role="row"> <tr
v-if="templates['groupfooter'] && rowGroupMode === 'subheader' && shouldRenderRowGroupFooter(value, rowData, getRowIndex(index))"
:key="getRowKey(rowData, getRowIndex(index)) + '_subfooter'"
class="p-rowgroup-footer"
role="row"
v-bind="ptm('rowgroupFooter')"
>
<td :colspan="columnsLength - 1"> <td :colspan="columnsLength - 1">
<component :is="templates['groupfooter']" :data="rowData" :index="getRowIndex(index)" /> <component :is="templates['groupfooter']" :data="rowData" :index="getRowIndex(index)" />
</td> </td>
</tr> </tr>
</template> </template>
</template> </template>
<tr v-else class="p-datatable-emptymessage" role="row"> <tr v-else class="p-datatable-emptymessage" role="row" v-bind="ptm('emptyMessage')">
<td :colspan="columnsLength"> <td :colspan="columnsLength">
<component v-if="templates.empty" :is="templates.empty" /> <component v-if="templates.empty" :is="templates.empty" />
</td> </td>
@ -97,6 +113,7 @@
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import ChevronDownIcon from 'primevue/icons/chevrondown'; import ChevronDownIcon from 'primevue/icons/chevrondown';
import ChevronRightIcon from 'primevue/icons/chevronright'; import ChevronRightIcon from 'primevue/icons/chevronright';
import { DomHandler, ObjectUtils, UniqueComponentId } from 'primevue/utils'; import { DomHandler, ObjectUtils, UniqueComponentId } from 'primevue/utils';
@ -104,6 +121,7 @@ import BodyCell from './BodyCell.vue';
export default { export default {
name: 'TableBody', name: 'TableBody',
extends: BaseComponent,
emits: [ emits: [
'rowgroup-toggle', 'rowgroup-toggle',
'row-click', 'row-click',

View file

@ -1,14 +1,14 @@
<template> <template>
<tfoot v-if="hasFooter" class="p-datatable-tfoot" role="rowgroup"> <tfoot v-if="hasFooter" class="p-datatable-tfoot" role="rowgroup" v-bind="ptm('tfoot')">
<tr v-if="!columnGroup" role="row"> <tr v-if="!columnGroup" role="row" v-bind="ptm('footerRow')">
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i"> <template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
<DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" /> <DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" :pt="pt" />
</template> </template>
</tr> </tr>
<template v-else> <template v-else>
<tr v-for="(row, i) of getFooterRows()" :key="i" role="row"> <tr v-for="(row, i) of getFooterRows()" :key="i" role="row" v-bind="ptm('footerRow')">
<template v-for="(col, j) of getFooterColumns(row)" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || j"> <template v-for="(col, j) of getFooterColumns(row)" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || j">
<DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" /> <DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" :pt="pt" />
</template> </template>
</tr> </tr>
</template> </template>
@ -16,11 +16,13 @@
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import { ObjectUtils } from 'primevue/utils'; import { ObjectUtils } from 'primevue/utils';
import FooterCell from './FooterCell.vue'; import FooterCell from './FooterCell.vue';
export default { export default {
name: 'TableFooter', name: 'TableFooter',
extends: BaseComponent,
props: { props: {
columnGroup: { columnGroup: {
type: null, type: null,

View file

@ -1,7 +1,7 @@
<template> <template>
<thead class="p-datatable-thead" role="rowgroup"> <thead class="p-datatable-thead" role="rowgroup" v-bind="ptm('thead')">
<template v-if="!columnGroup"> <template v-if="!columnGroup">
<tr role="row"> <tr role="row" v-bind="ptm('headerRow')">
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i"> <template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
<DTHeaderCell <DTHeaderCell
v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field'))" v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field'))"
@ -36,13 +36,14 @@
@constraint-remove="$emit('constraint-remove', $event)" @constraint-remove="$emit('constraint-remove', $event)"
@apply-click="$emit('apply-click', $event)" @apply-click="$emit('apply-click', $event)"
:headerCheckboxIconTemplate="headerCheckboxIconTemplate" :headerCheckboxIconTemplate="headerCheckboxIconTemplate"
:pt="pt"
/> />
</template> </template>
</tr> </tr>
<tr v-if="filterDisplay === 'row'" role="row"> <tr v-if="filterDisplay === 'row'" role="row" v-bind="ptm('headerRow')">
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i"> <template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
<th v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field'))" :style="getFilterColumnHeaderStyle(col)" :class="getFilterColumnHeaderClass(col)"> <th v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field'))" :style="getFilterColumnHeaderStyle(col)" :class="getFilterColumnHeaderClass(col)" v-bind="ptm('headerCell')">
<DTHeaderCheckbox v-if="columnProp(col, 'selectionMode') === 'multiple'" :checked="allRowsSelected" :disabled="empty" @change="$emit('checkbox-change', $event)" /> <DTHeaderCheckbox v-if="columnProp(col, 'selectionMode') === 'multiple'" :checked="allRowsSelected" :disabled="empty" @change="$emit('checkbox-change', $event)" :pt="pt" />
<DTColumnFilter <DTColumnFilter
v-if="col.children && col.children.filter" v-if="col.children && col.children.filter"
:field="columnProp(col, 'filterField') || columnProp(col, 'field')" :field="columnProp(col, 'filterField') || columnProp(col, 'field')"
@ -77,13 +78,14 @@
@constraint-add="$emit('constraint-add', $event)" @constraint-add="$emit('constraint-add', $event)"
@constraint-remove="$emit('constraint-remove', $event)" @constraint-remove="$emit('constraint-remove', $event)"
@apply-click="$emit('apply-click', $event)" @apply-click="$emit('apply-click', $event)"
:pt="pt"
/> />
</th> </th>
</template> </template>
</tr> </tr>
</template> </template>
<template v-else> <template v-else>
<tr v-for="(row, i) of getHeaderRows()" :key="i" role="row"> <tr v-for="(row, i) of getHeaderRows()" :key="i" role="row" v-bind="ptm('headerRow')">
<template v-for="(col, j) of getHeaderColumns(row)" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || j"> <template v-for="(col, j) of getHeaderColumns(row)" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || j">
<DTHeaderCell <DTHeaderCell
v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field')) && typeof col.children !== 'string'" v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field')) && typeof col.children !== 'string'"
@ -110,6 +112,7 @@
@constraint-remove="$emit('constraint-remove', $event)" @constraint-remove="$emit('constraint-remove', $event)"
@apply-click="$emit('apply-click', $event)" @apply-click="$emit('apply-click', $event)"
:headerCheckboxIconTemplate="headerCheckboxIconTemplate" :headerCheckboxIconTemplate="headerCheckboxIconTemplate"
:pt="pt"
/> />
</template> </template>
</tr> </tr>
@ -118,6 +121,7 @@
</template> </template>
<script> <script>
import BaseComponent from 'primevue/basecomponent';
import { ObjectUtils } from 'primevue/utils'; import { ObjectUtils } from 'primevue/utils';
import ColumnFilter from './ColumnFilter.vue'; import ColumnFilter from './ColumnFilter.vue';
import HeaderCell from './HeaderCell.vue'; import HeaderCell from './HeaderCell.vue';
@ -125,6 +129,7 @@ import HeaderCheckbox from './HeaderCheckbox.vue';
export default { export default {
name: 'TableHeader', name: 'TableHeader',
extends: BaseComponent,
emits: [ emits: [
'column-click', 'column-click',
'column-mousedown', 'column-mousedown',

View file

@ -1,25 +0,0 @@
<template>
<tbody class="p-datatable-tbody">
<tr v-for="n in rows" :key="n" role="row">
<td v-for="(col, i) of columns" :key="col.props.columnKey || col.props.field || i">
<component v-if="col.children && col.children.loading" :is="col.children.loading" :column="col" :index="i" />
</td>
</tr>
</tbody>
</template>
<script>
export default {
name: 'TableLoadingBody',
props: {
columns: {
type: null,
default: null
},
rows: {
type: null,
default: null
}
}
};
</script>