Components added. Build issues fixed
parent
5b66ed1093
commit
18c3721848
|
@ -16,7 +16,12 @@ export interface AccordionTabOpenEvent {
|
|||
/**
|
||||
* @extends {AccordionTabOpenEvent}
|
||||
*/
|
||||
export interface AccordionTabCloseEvent extends AccordionTabOpenEvent { }
|
||||
export interface AccordionTabCloseEvent extends AccordionTabOpenEvent {}
|
||||
|
||||
/**
|
||||
* @extends AccordionTabOpenEvent
|
||||
*/
|
||||
export interface AccordionClickEvent extends AccordionTabOpenEvent {}
|
||||
|
||||
export interface AccordionProps {
|
||||
/**
|
||||
|
@ -39,6 +44,14 @@ export interface AccordionProps {
|
|||
* Icon of an expanded tab.
|
||||
*/
|
||||
collapseIcon?: string | undefined;
|
||||
/**
|
||||
* Index of the element in tabbing order.
|
||||
*/
|
||||
tabindex?: number | undefined;
|
||||
/**
|
||||
* When enabled, the focused tab is activated.
|
||||
*/
|
||||
selectOnFocus?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface AccordionSlots {
|
||||
|
@ -64,13 +77,18 @@ export declare type AccordionEmits = {
|
|||
* @param {AccordionTabCloseEvent} event - Custom tab close event.
|
||||
*/
|
||||
'tab-close': (event: AccordionTabCloseEvent) => void;
|
||||
}
|
||||
/**
|
||||
* Callback to invoke when an active tab is clicked.
|
||||
* @param {AccordionClickEvent} event - Custom tab click event.
|
||||
*/
|
||||
'tab-click': (event: AccordionClickEvent) => void;
|
||||
};
|
||||
|
||||
declare class Accordion extends ClassComponent<AccordionProps, AccordionSlots, AccordionEmits> { }
|
||||
declare class Accordion extends ClassComponent<AccordionProps, AccordionSlots, AccordionEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Accordion: GlobalComponentConstructor<Accordion>
|
||||
Accordion: GlobalComponentConstructor<Accordion>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +102,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Accordion](https://www.primefaces.org/primevue/showcase/#/accordion)
|
||||
* - [Accordion](https://www.primefaces.org/primevue/accordion)
|
||||
*
|
||||
*/
|
||||
export default Accordion;
|
||||
|
|
|
@ -39,7 +39,7 @@ describe('Accordion.vue', () => {
|
|||
expect(wrapper.findAll('.p-accordion-tab').length).toBe(3);
|
||||
});
|
||||
|
||||
it('should activeIndex change', async() => {
|
||||
it('should activeIndex change', async () => {
|
||||
await wrapper.setProps({ activeIndex: 1 });
|
||||
|
||||
const allTabs = wrapper.findAll('.p-accordion-tab');
|
||||
|
|
|
@ -1,17 +1,35 @@
|
|||
<template>
|
||||
<div class="p-accordion p-component">
|
||||
<div v-for="(tab,i) of tabs" :key="getKey(tab,i)" :class="getTabClass(i)">
|
||||
<div :class="getTabHeaderClass(tab, i)">
|
||||
<a role="tab" class="p-accordion-header-link" @click="onTabClick($event, tab, i)" @keydown="onTabKeydown($event, tab, i)" :tabindex="isTabDisabled(tab) ? null : '0'"
|
||||
:aria-expanded="isTabActive(i)" :id="getTabAriaId(i) + '_header'" :aria-controls="getTabAriaId(i) + '_content'">
|
||||
<span :class="isTabActive(i) ? getHeaderCollapseIcon() : getHeaderExpandIcon()"></span>
|
||||
<span class="p-accordion-header-text" v-if="tab.props && tab.props.header">{{tab.props.header}}</span>
|
||||
<component :is="tab.children.header" v-if="tab.children && tab.children.header"></component>
|
||||
<div v-for="(tab, i) of tabs" :key="getKey(tab, i)" :class="getTabClass(i)" :data-index="i">
|
||||
<div :style="getTabProp(tab, 'headerStyle')" :class="getTabHeaderClass(tab, i)" v-bind="getTabProp(tab, 'headerProps')">
|
||||
<a
|
||||
:id="getTabHeaderActionId(i)"
|
||||
class="p-accordion-header-link p-accordion-header-action"
|
||||
:tabindex="getTabProp(tab, 'disabled') ? -1 : tabindex"
|
||||
role="button"
|
||||
:aria-disabled="getTabProp(tab, 'disabled')"
|
||||
:aria-expanded="isTabActive(i)"
|
||||
:aria-controls="getTabContentId(i)"
|
||||
@click="onTabClick($event, tab, i)"
|
||||
@keydown="onTabKeyDown($event, tab, i)"
|
||||
v-bind="getTabProp(tab, 'headerActionProps')"
|
||||
>
|
||||
<span :class="getTabHeaderIconClass(i)" aria-hidden="true"></span>
|
||||
<span v-if="tab.props && tab.props.header" class="p-accordion-header-text">{{ tab.props.header }}</span>
|
||||
<component v-if="tab.children && tab.children.header" :is="tab.children.header"></component>
|
||||
</a>
|
||||
</div>
|
||||
<transition name="p-toggleable-content">
|
||||
<div class="p-toggleable-content" v-if="lazy ? isTabActive(i) : true" v-show="lazy ? true: isTabActive(i)"
|
||||
role="region" :id="getTabAriaId(i) + '_content'" :aria-labelledby="getTabAriaId(i) + '_header'">
|
||||
<div
|
||||
v-if="lazy ? isTabActive(i) : true"
|
||||
v-show="lazy ? true : isTabActive(i)"
|
||||
:id="getTabContentId(i)"
|
||||
:style="getTabProp(tab, 'contentStyle')"
|
||||
:class="getTabContentClass(tab)"
|
||||
role="region"
|
||||
:aria-labelledby="getTabHeaderActionId(i)"
|
||||
v-bind="getTabProp(tab, 'contentProps')"
|
||||
>
|
||||
<div class="p-accordion-content">
|
||||
<component :is="tab"></component>
|
||||
</div>
|
||||
|
@ -22,18 +40,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {UniqueComponentId} from 'primevue/utils';
|
||||
import { UniqueComponentId, DomHandler } from 'primevue/utils';
|
||||
import Ripple from 'primevue/ripple';
|
||||
|
||||
export default {
|
||||
name: 'Accordion',
|
||||
emits: ['tab-close', 'tab-open', 'update:activeIndex'],
|
||||
emits: ['update:activeIndex', 'tab-open', 'tab-close', 'tab-click'],
|
||||
props: {
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
activeIndex: {
|
||||
type: [Number,Array],
|
||||
type: [Number, Array],
|
||||
default: null
|
||||
},
|
||||
lazy: {
|
||||
|
@ -47,12 +66,20 @@ export default {
|
|||
collapseIcon: {
|
||||
type: String,
|
||||
default: 'pi-chevron-down'
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
selectOnFocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
d_activeIndex: this.activeIndex
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
activeIndex(newValue) {
|
||||
|
@ -60,97 +87,187 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
onTabClick(event, tab, i) {
|
||||
if (!this.isTabDisabled(tab)) {
|
||||
const active = this.isTabActive(i);
|
||||
isAccordionTab(child) {
|
||||
return child.type.name === 'AccordionTab';
|
||||
},
|
||||
isTabActive(index) {
|
||||
return this.multiple ? this.d_activeIndex && this.d_activeIndex.includes(index) : this.d_activeIndex === index;
|
||||
},
|
||||
getTabProp(tab, name) {
|
||||
return tab.props ? tab.props[name] : undefined;
|
||||
},
|
||||
getKey(tab, index) {
|
||||
return this.getTabProp(tab, 'header') || index;
|
||||
},
|
||||
getTabHeaderActionId(index) {
|
||||
return `${this.id}_${index}_header_action`;
|
||||
},
|
||||
getTabContentId(index) {
|
||||
return `${this.id}_${index}_content`;
|
||||
},
|
||||
onTabClick(event, tab, index) {
|
||||
this.changeActiveIndex(event, tab, index);
|
||||
this.$emit('tab-click', { originalEvent: event, index });
|
||||
},
|
||||
onTabKeyDown(event, tab, index) {
|
||||
switch (event.code) {
|
||||
case 'ArrowDown':
|
||||
this.onTabArrowDownKey(event);
|
||||
break;
|
||||
|
||||
case 'ArrowUp':
|
||||
this.onTabArrowUpKey(event);
|
||||
break;
|
||||
|
||||
case 'Home':
|
||||
this.onTabHomeKey(event);
|
||||
break;
|
||||
|
||||
case 'End':
|
||||
this.onTabEndKey(event);
|
||||
break;
|
||||
|
||||
case 'Enter':
|
||||
case 'Space':
|
||||
this.onTabEnterKey(event, tab, index);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
onTabArrowDownKey(event) {
|
||||
const nextHeaderAction = this.findNextHeaderAction(event.target.parentElement.parentElement);
|
||||
|
||||
nextHeaderAction ? this.changeFocusedTab(event, nextHeaderAction) : this.onTabHomeKey(event);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabArrowUpKey(event) {
|
||||
const prevHeaderAction = this.findPrevHeaderAction(event.target.parentElement.parentElement);
|
||||
|
||||
prevHeaderAction ? this.changeFocusedTab(event, prevHeaderAction) : this.onTabEndKey(event);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabHomeKey(event) {
|
||||
const firstHeaderAction = this.findFirstHeaderAction();
|
||||
|
||||
this.changeFocusedTab(event, firstHeaderAction);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabEndKey(event) {
|
||||
const lastHeaderAction = this.findLastHeaderAction();
|
||||
|
||||
this.changeFocusedTab(event, lastHeaderAction);
|
||||
event.preventDefault();
|
||||
},
|
||||
onTabEnterKey(event, tab, index) {
|
||||
this.changeActiveIndex(event, tab, index);
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
findNextHeaderAction(tabElement, selfCheck = false) {
|
||||
const nextTabElement = selfCheck ? tabElement : tabElement.nextElementSibling;
|
||||
const headerElement = DomHandler.findSingle(nextTabElement, '.p-accordion-header');
|
||||
|
||||
return headerElement ? (DomHandler.hasClass(headerElement, 'p-disabled') ? this.findNextHeaderAction(headerElement.parentElement) : DomHandler.findSingle(headerElement, '.p-accordion-header-action')) : null;
|
||||
},
|
||||
findPrevHeaderAction(tabElement, selfCheck = false) {
|
||||
const prevTabElement = selfCheck ? tabElement : tabElement.previousElementSibling;
|
||||
const headerElement = DomHandler.findSingle(prevTabElement, '.p-accordion-header');
|
||||
|
||||
return headerElement ? (DomHandler.hasClass(headerElement, 'p-disabled') ? this.findPrevHeaderAction(headerElement.parentElement) : DomHandler.findSingle(headerElement, '.p-accordion-header-action')) : null;
|
||||
},
|
||||
findFirstHeaderAction() {
|
||||
return this.findNextHeaderAction(this.$el.firstElementChild, true);
|
||||
},
|
||||
findLastHeaderAction() {
|
||||
return this.findPrevHeaderAction(this.$el.lastElementChild, true);
|
||||
},
|
||||
changeActiveIndex(event, tab, index) {
|
||||
if (!this.getTabProp(tab, 'disabled')) {
|
||||
const active = this.isTabActive(index);
|
||||
const eventName = active ? 'tab-close' : 'tab-open';
|
||||
|
||||
if (this.multiple) {
|
||||
if (active) {
|
||||
this.d_activeIndex = this.d_activeIndex.filter(index => index !== i);
|
||||
this.d_activeIndex = this.d_activeIndex.filter((i) => i !== index);
|
||||
} else {
|
||||
if (this.d_activeIndex) this.d_activeIndex.push(index);
|
||||
else this.d_activeIndex = [index];
|
||||
}
|
||||
else {
|
||||
if (this.d_activeIndex)
|
||||
this.d_activeIndex.push(i);
|
||||
else
|
||||
this.d_activeIndex = [i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.d_activeIndex = this.d_activeIndex === i ? null : i;
|
||||
} else {
|
||||
this.d_activeIndex = this.d_activeIndex === index ? null : index;
|
||||
}
|
||||
|
||||
this.$emit('update:activeIndex', this.d_activeIndex);
|
||||
this.$emit(eventName, { originalEvent: event, index });
|
||||
}
|
||||
},
|
||||
changeFocusedTab(event, element) {
|
||||
if (element) {
|
||||
DomHandler.focus(element);
|
||||
|
||||
this.$emit(eventName, {
|
||||
originalEvent: event,
|
||||
index: i
|
||||
});
|
||||
if (this.selectOnFocus) {
|
||||
const index = parseInt(element.parentElement.parentElement.dataset.index, 10);
|
||||
const tab = this.tabs[index];
|
||||
|
||||
this.changeActiveIndex(event, tab, index);
|
||||
}
|
||||
}
|
||||
},
|
||||
onTabKeydown(event, tab, i) {
|
||||
if (event.which === 13) {
|
||||
this.onTabClick(event, tab, i);
|
||||
}
|
||||
},
|
||||
isTabActive(index) {
|
||||
if (this.multiple)
|
||||
return this.d_activeIndex && this.d_activeIndex.includes(index);
|
||||
else
|
||||
return index === this.d_activeIndex;
|
||||
},
|
||||
getKey(tab, i) {
|
||||
return (tab.props && tab.props.header) ? tab.props.header : i;
|
||||
},
|
||||
isTabDisabled(tab) {
|
||||
return tab.props && tab.props.disabled;
|
||||
},
|
||||
getTabClass(i) {
|
||||
return ['p-accordion-tab', {'p-accordion-tab-active': this.isTabActive(i)}];
|
||||
return [
|
||||
'p-accordion-tab',
|
||||
{
|
||||
'p-accordion-tab-active': this.isTabActive(i)
|
||||
}
|
||||
];
|
||||
},
|
||||
getTabHeaderClass(tab, i) {
|
||||
return ['p-accordion-header', {'p-highlight': this.isTabActive(i), 'p-disabled': this.isTabDisabled(tab)}];
|
||||
return [
|
||||
'p-accordion-header',
|
||||
this.getTabProp(tab, 'headerClass'),
|
||||
{
|
||||
'p-highlight': this.isTabActive(i),
|
||||
'p-disabled': this.getTabProp(tab, 'disabled')
|
||||
}
|
||||
];
|
||||
},
|
||||
getTabAriaId(i) {
|
||||
return this.ariaId + '_' + i;
|
||||
getTabHeaderIconClass(i) {
|
||||
return ['p-accordion-toggle-icon pi', this.isTabActive(i) ? this.collapseIcon : this.expandIcon];
|
||||
},
|
||||
getHeaderCollapseIcon() {
|
||||
return ['p-accordion-toggle-icon pi', this.collapseIcon];
|
||||
},
|
||||
getHeaderExpandIcon() {
|
||||
return ['p-accordion-toggle-icon pi', this.expandIcon];
|
||||
},
|
||||
isAccordionTab(child) {
|
||||
return child.type.name === 'AccordionTab';
|
||||
getTabContentClass(tab) {
|
||||
return ['p-toggleable-content', this.getTabProp(tab, 'contentClass')];
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tabs() {
|
||||
const tabs = []
|
||||
this.$slots.default().forEach(child => {
|
||||
if (this.isAccordionTab(child)) {
|
||||
tabs.push(child);
|
||||
}
|
||||
else if (child.children && child.children instanceof Array) {
|
||||
child.children.forEach(nestedChild => {
|
||||
if (this.isAccordionTab(nestedChild)) {
|
||||
tabs.push(nestedChild)
|
||||
}
|
||||
});
|
||||
}
|
||||
return this.$slots.default().reduce((tabs, child) => {
|
||||
if (this.isAccordionTab(child)) {
|
||||
tabs.push(child);
|
||||
} else if (child.children && child.children instanceof Array) {
|
||||
child.children.forEach((nestedChild) => {
|
||||
if (this.isAccordionTab(nestedChild)) {
|
||||
tabs.push(nestedChild);
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
return tabs;
|
||||
|
||||
return tabs;
|
||||
}, []);
|
||||
},
|
||||
ariaId() {
|
||||
return UniqueComponentId();
|
||||
id() {
|
||||
return this.$attrs.id || UniqueComponentId();
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
ripple: Ripple
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-accordion-header-link {
|
||||
.p-accordion-header-action {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -159,7 +276,7 @@ export default {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.p-accordion-header-link:focus {
|
||||
.p-accordion-header-action:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { VNode } from 'vue';
|
||||
import { AnchorHTMLAttributes, HTMLAttributes, VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
export interface AccordionTabProps {
|
||||
|
@ -6,6 +6,34 @@ export interface AccordionTabProps {
|
|||
* Orientation of tab headers.
|
||||
*/
|
||||
header?: string | undefined;
|
||||
/**
|
||||
* Inline style of the tab header.
|
||||
*/
|
||||
headerStyle?: any;
|
||||
/**
|
||||
* Style class of the tab header.
|
||||
*/
|
||||
headerClass?: any;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLDivElement to the tab header.
|
||||
*/
|
||||
headerProps?: HTMLAttributes | undefined;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLAnchorElement to the focusable anchor element inside the tab header.
|
||||
*/
|
||||
headerActionProps?: AnchorHTMLAttributes | undefined;
|
||||
/**
|
||||
* Inline style of the tab content.
|
||||
*/
|
||||
contentStyle?: any;
|
||||
/**
|
||||
* Style class of the tab content.
|
||||
*/
|
||||
contentClass?: any;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLDivElement to the tab content.
|
||||
*/
|
||||
contentProps?: HTMLAttributes | undefined;
|
||||
/**
|
||||
* Whether the tab is disabled.
|
||||
*/
|
||||
|
@ -23,13 +51,13 @@ export interface AccordionTabSlots {
|
|||
header: () => VNode[];
|
||||
}
|
||||
|
||||
export declare type AccordionTabEmits = { }
|
||||
export declare type AccordionTabEmits = {};
|
||||
|
||||
declare class AccordionTab extends ClassComponent<AccordionTabProps, AccordionTabSlots, AccordionTabEmits> { }
|
||||
declare class AccordionTab extends ClassComponent<AccordionTabProps, AccordionTabSlots, AccordionTabEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
AccordionTab: GlobalComponentConstructor<AccordionTab>
|
||||
AccordionTab: GlobalComponentConstructor<AccordionTab>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +67,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Accordion](https://www.primefaces.org/primevue/showcase/#/accordion)
|
||||
* - [Accordion](https://www.primefaces.org/primevue/accordion)
|
||||
*
|
||||
*/
|
||||
export default AccordionTab;
|
||||
|
|
|
@ -7,7 +7,14 @@ export default {
|
|||
name: 'AccordionTab',
|
||||
props: {
|
||||
header: null,
|
||||
headerStyle: null,
|
||||
headerClass: null,
|
||||
headerProps: null,
|
||||
headerActionProps: null,
|
||||
contentStyle: null,
|
||||
contentClass: null,
|
||||
contentProps: null,
|
||||
disabled: Boolean
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -144,7 +144,7 @@ export interface PrimeIconsOptions {
|
|||
readonly ENVELOPE: string;
|
||||
readonly EURO: string;
|
||||
readonly EXCLAMATION_CIRCLE: string;
|
||||
readonly EXCLAMATION_TRIANGLE : string;
|
||||
readonly EXCLAMATION_TRIANGLE: string;
|
||||
readonly EXTERNAL_LINK: string;
|
||||
readonly EYE: string;
|
||||
readonly EYE_SLASH: string;
|
||||
|
|
|
@ -4,4 +4,4 @@ import FilterService from './FilterService';
|
|||
import PrimeIcons from './PrimeIcons';
|
||||
import ToastSeverity from './ToastSeverity';
|
||||
|
||||
export {FilterMatchMode,FilterOperator,FilterService,PrimeIcons,ToastSeverity};
|
||||
export { FilterMatchMode, FilterOperator, FilterService, PrimeIcons, ToastSeverity };
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
const FilterMatchMode = {
|
||||
STARTS_WITH : 'startsWith',
|
||||
CONTAINS : 'contains',
|
||||
NOT_CONTAINS : 'notContains',
|
||||
ENDS_WITH : 'endsWith',
|
||||
EQUALS : 'equals',
|
||||
NOT_EQUALS : 'notEquals',
|
||||
IN : 'in',
|
||||
LESS_THAN : 'lt',
|
||||
LESS_THAN_OR_EQUAL_TO : 'lte',
|
||||
GREATER_THAN : 'gt',
|
||||
GREATER_THAN_OR_EQUAL_TO : 'gte',
|
||||
BETWEEN : 'between',
|
||||
DATE_IS : 'dateIs',
|
||||
DATE_IS_NOT : 'dateIsNot',
|
||||
DATE_BEFORE : 'dateBefore',
|
||||
DATE_AFTER : 'dateAfter'
|
||||
}
|
||||
STARTS_WITH: 'startsWith',
|
||||
CONTAINS: 'contains',
|
||||
NOT_CONTAINS: 'notContains',
|
||||
ENDS_WITH: 'endsWith',
|
||||
EQUALS: 'equals',
|
||||
NOT_EQUALS: 'notEquals',
|
||||
IN: 'in',
|
||||
LESS_THAN: 'lt',
|
||||
LESS_THAN_OR_EQUAL_TO: 'lte',
|
||||
GREATER_THAN: 'gt',
|
||||
GREATER_THAN_OR_EQUAL_TO: 'gte',
|
||||
BETWEEN: 'between',
|
||||
DATE_IS: 'dateIs',
|
||||
DATE_IS_NOT: 'dateIsNot',
|
||||
DATE_BEFORE: 'dateBefore',
|
||||
DATE_AFTER: 'dateAfter'
|
||||
};
|
||||
|
||||
export default FilterMatchMode;
|
|
@ -1,6 +1,6 @@
|
|||
const FilterOperator = {
|
||||
AND: 'and',
|
||||
OR: 'or'
|
||||
}
|
||||
};
|
||||
|
||||
export default FilterOperator;
|
|
@ -1,4 +1,4 @@
|
|||
import {ObjectUtils} from 'primevue/utils';
|
||||
import { ObjectUtils } from 'primevue/utils';
|
||||
|
||||
const FilterService = {
|
||||
filter(value, fields, filterValue, filterMatchMode, filterLocale) {
|
||||
|
@ -20,7 +20,7 @@ const FilterService = {
|
|||
return filteredItems;
|
||||
},
|
||||
filters: {
|
||||
startsWith(value, filter, filterLocale) {
|
||||
startsWith(value, filter, filterLocale) {
|
||||
if (filter === undefined || filter === null || filter.trim() === '') {
|
||||
return true;
|
||||
}
|
||||
|
@ -85,10 +85,8 @@ const FilterService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (value.getTime && filter.getTime)
|
||||
return value.getTime() === filter.getTime();
|
||||
else
|
||||
return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) == ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
|
||||
if (value.getTime && filter.getTime) return value.getTime() === filter.getTime();
|
||||
else return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) == ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
|
||||
},
|
||||
notEquals(value, filter, filterLocale) {
|
||||
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
|
||||
|
@ -99,10 +97,8 @@ const FilterService = {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (value.getTime && filter.getTime)
|
||||
return value.getTime() !== filter.getTime();
|
||||
else
|
||||
return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) != ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
|
||||
if (value.getTime && filter.getTime) return value.getTime() !== filter.getTime();
|
||||
else return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) != ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale);
|
||||
},
|
||||
in(value, filter) {
|
||||
if (filter === undefined || filter === null || filter.length === 0) {
|
||||
|
@ -126,10 +122,8 @@ const FilterService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (value.getTime)
|
||||
return filter[0].getTime() <= value.getTime() && value.getTime() <= filter[1].getTime();
|
||||
else
|
||||
return filter[0] <= value && value <= filter[1];
|
||||
if (value.getTime) return filter[0].getTime() <= value.getTime() && value.getTime() <= filter[1].getTime();
|
||||
else return filter[0] <= value && value <= filter[1];
|
||||
},
|
||||
lt(value, filter) {
|
||||
if (filter === undefined || filter === null) {
|
||||
|
@ -140,10 +134,8 @@ const FilterService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (value.getTime && filter.getTime)
|
||||
return value.getTime() < filter.getTime();
|
||||
else
|
||||
return value < filter;
|
||||
if (value.getTime && filter.getTime) return value.getTime() < filter.getTime();
|
||||
else return value < filter;
|
||||
},
|
||||
lte(value, filter) {
|
||||
if (filter === undefined || filter === null) {
|
||||
|
@ -154,10 +146,8 @@ const FilterService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (value.getTime && filter.getTime)
|
||||
return value.getTime() <= filter.getTime();
|
||||
else
|
||||
return value <= filter;
|
||||
if (value.getTime && filter.getTime) return value.getTime() <= filter.getTime();
|
||||
else return value <= filter;
|
||||
},
|
||||
gt(value, filter) {
|
||||
if (filter === undefined || filter === null) {
|
||||
|
@ -168,10 +158,8 @@ const FilterService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (value.getTime && filter.getTime)
|
||||
return value.getTime() > filter.getTime();
|
||||
else
|
||||
return value > filter;
|
||||
if (value.getTime && filter.getTime) return value.getTime() > filter.getTime();
|
||||
else return value > filter;
|
||||
},
|
||||
gte(value, filter) {
|
||||
if (filter === undefined || filter === null) {
|
||||
|
@ -182,10 +170,8 @@ const FilterService = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (value.getTime && filter.getTime)
|
||||
return value.getTime() >= filter.getTime();
|
||||
else
|
||||
return value >= filter;
|
||||
if (value.getTime && filter.getTime) return value.getTime() >= filter.getTime();
|
||||
else return value >= filter;
|
||||
},
|
||||
dateIs(value, filter) {
|
||||
if (filter === undefined || filter === null) {
|
||||
|
@ -235,6 +221,6 @@ const FilterService = {
|
|||
register(rule, fn) {
|
||||
this.filters[rule] = fn;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default FilterService;
|
|
@ -1,240 +1,240 @@
|
|||
const PrimeIcons = {
|
||||
ALIGN_CENTER:'pi pi-align-center',
|
||||
ALIGN_JUSTIFY:'pi pi-align-justify',
|
||||
ALIGN_LEFT:'pi pi-align-left',
|
||||
ALIGN_RIGHT:'pi pi-align-right',
|
||||
AMAZON:'pi pi-amazon',
|
||||
ANDROID:'pi pi-android',
|
||||
ANGLE_DOUBLE_DOWN:'pi pi-angle-double-down',
|
||||
ANGLE_DOUBLE_LEFT:'pi pi-angle-double-left',
|
||||
ANGLE_DOUBLE_RIGHT:'pi pi-angle-double-right',
|
||||
ANGLE_DOUBLE_UP:'pi pi-angle-double-up',
|
||||
ANGLE_DOWN:'pi pi-angle-down',
|
||||
ANGLE_LEFT:'pi pi-angle-left',
|
||||
ANGLE_RIGHT:'pi pi-angle-right',
|
||||
ANGLE_UP:'pi pi-angle-up',
|
||||
APPLE:'pi pi-apple',
|
||||
ARROW_CIRCLE_DOWN:'pi pi-arrow-circle-down',
|
||||
ARROW_CIRCLE_LEFT:'pi pi-arrow-circle-left',
|
||||
ARROW_CIRCLE_RIGHT:'pi pi-arrow-circle-right',
|
||||
ARROW_CIRCLE_UP:'pi pi-arrow-circle-up',
|
||||
ARROW_DOWN:'pi pi-arrow-down',
|
||||
ARROW_DOWN_LEFT:'pi pi-arrow-down-left',
|
||||
ARROW_DOWN_RIGHT:'pi pi-arrow-down-right',
|
||||
ARROW_LEFT:'pi pi-arrow-left',
|
||||
ARROW_RIGHT:'pi pi-arrow-right',
|
||||
ARROW_UP:'pi pi-arrow-up',
|
||||
ARROW_UP_LEFT:'pi pi-arrow-up-left',
|
||||
ARROW_UP_RIGHT:'pi pi-arrow-up-right',
|
||||
ARROW_H:'pi pi-arrow-h',
|
||||
ARROW_V:'pi pi-arrow-v',
|
||||
AT:'pi pi-at',
|
||||
BACKWARD:'pi pi-backward',
|
||||
BAN:'pi pi-ban',
|
||||
BARS:'pi pi-bars',
|
||||
BELL:'pi pi-bell',
|
||||
BOLT:'pi pi-bolt',
|
||||
BOOK:'pi pi-book',
|
||||
BOOKMARK:'pi pi-bookmark',
|
||||
BOOKMARK_FILL:'pi pi-bookmark-fill',
|
||||
BOX:'pi pi-box',
|
||||
BRIEFCASE:'pi pi-briefcase',
|
||||
BUILDING:'pi pi-building',
|
||||
CALENDAR:'pi pi-calendar',
|
||||
CALENDAR_MINUS:'pi pi-calendar-minus',
|
||||
CALENDAR_PLUS:'pi pi-calendar-plus',
|
||||
CALENDAR_TIMES:'pi pi-calendar-times',
|
||||
CAMERA:'pi pi-camera',
|
||||
CAR:'pi pi-car',
|
||||
CARET_DOWN:'pi pi-caret-down',
|
||||
CARET_LEFT:'pi pi-caret-left',
|
||||
CARET_RIGHT:'pi pi-caret-right',
|
||||
CARET_UP:'pi pi-caret-up',
|
||||
CHART_BAR:'pi pi-chart-bar',
|
||||
CHART_LINE:'pi pi-chart-line',
|
||||
CHART_PIE:'pi pi-chart-pie',
|
||||
CHECK:'pi pi-check',
|
||||
CHECK_CIRCLE:'pi pi-check-circle',
|
||||
CHECK_SQUARE:'pi pi-check-square',
|
||||
CHEVRON_CIRCLE_DOWN:'pi pi-chevron-circle-down',
|
||||
CHEVRON_CIRCLE_LEFT:'pi pi-chevron-circle-left',
|
||||
CHEVRON_CIRCLE_RIGHT:'pi pi-chevron-circle-right',
|
||||
CHEVRON_CIRCLE_UP:'pi pi-chevron-circle-up',
|
||||
CHEVRON_DOWN:'pi pi-chevron-down',
|
||||
CHEVRON_LEFT:'pi pi-chevron-left',
|
||||
CHEVRON_RIGHT:'pi pi-chevron-right',
|
||||
CHEVRON_UP:'pi pi-chevron-up',
|
||||
CIRCLE:'pi pi-circle',
|
||||
CIRCLE_FILL:'pi pi-circle-fill',
|
||||
CLOCK:'pi pi-clock',
|
||||
CLONE:'pi pi-clone',
|
||||
CLOUD:'pi pi-cloud',
|
||||
CLOUD_DOWNLOAD:'pi pi-cloud-download',
|
||||
CLOUD_UPLOAD:'pi pi-cloud-upload',
|
||||
CODE:'pi pi-code',
|
||||
COG:'pi pi-cog',
|
||||
COMMENT:'pi pi-comment',
|
||||
COMMENTS:'pi pi-comments',
|
||||
COMPASS:'pi pi-compass',
|
||||
COPY:'pi pi-copy',
|
||||
CREDIT_CARD:'pi pi-credit-card',
|
||||
DATABASE:'pi pi-database',
|
||||
DESKTOP:'pi pi-desktop',
|
||||
DIRECTIONS:'pi pi-directions',
|
||||
DIRECTIONS_ALT:'pi pi-directions-alt',
|
||||
DISCORD:'pi pi-discord',
|
||||
DOLLAR:'pi pi-dollar',
|
||||
DOWNLOAD:'pi pi-download',
|
||||
EJECT:'pi pi-eject',
|
||||
ELLIPSIS_H:'pi pi-ellipsis-h',
|
||||
ELLIPSIS_V:'pi pi-ellipsis-v',
|
||||
ENVELOPE:'pi pi-envelope',
|
||||
EURO:'pi pi-euro',
|
||||
EXCLAMATION_CIRCLE:'pi pi-exclamation-circle',
|
||||
EXCLAMATION_TRIANGLE :'pi pi-exclamation-triangle',
|
||||
EXTERNAL_LINK:'pi pi-external-link',
|
||||
EYE:'pi pi-eye',
|
||||
EYE_SLASH:'pi pi-eye-slash',
|
||||
FACEBOOK:'pi pi-facebook',
|
||||
FAST_BACKWARD:'pi pi-fast-backward',
|
||||
FAST_FORWARD:'pi pi-fast-forward',
|
||||
FILE:'pi pi-file',
|
||||
FILE_EXCEL:'pi pi-file-excel',
|
||||
FILE_PDF:'pi pi-file-pdf',
|
||||
FILTER:'pi pi-filter',
|
||||
FILTER_FILL:'pi pi-filter-fill',
|
||||
FILTER_SLASH:'pi pi-filter-slash',
|
||||
FLAG:'pi pi-flag',
|
||||
FLAG_FILL:'pi pi-flag-fill',
|
||||
FOLDER:'pi pi-folder',
|
||||
FOLDER_OPEN:'pi pi-folder-open',
|
||||
FORWARD:'pi pi-forward',
|
||||
GITHUB:'pi pi-github',
|
||||
GLOBE:'pi pi-globe',
|
||||
GOOGLE:'pi pi-google',
|
||||
HASHTAG:'pi pi-hashtag',
|
||||
HEART:'pi pi-heart',
|
||||
HEART_FILL:'pi pi-heart-fill',
|
||||
HISTORY:'pi pi-history',
|
||||
HOME:'pi pi-home',
|
||||
ID_CARD:'pi pi-id-card',
|
||||
IMAGE:'pi pi-image',
|
||||
IMAGES:'pi pi-images',
|
||||
INBOX:'pi pi-inbox',
|
||||
INFO:'pi pi-info',
|
||||
INFO_CIRCLE:'pi pi-info-circle',
|
||||
INSTAGRAM:'pi pi-instagram',
|
||||
KEY:'pi pi-key',
|
||||
LINK:'pi pi-link',
|
||||
LINKEDIN:'pi pi-linkedin',
|
||||
LIST:'pi pi-list',
|
||||
LOCK:'pi pi-lock',
|
||||
LOCK_OPEN:'pi pi-lock-open',
|
||||
MAP:'pi pi-map',
|
||||
MAP_MARKER:'pi pi-map-marker',
|
||||
MICROSOFT:'pi pi-microsoft',
|
||||
MINUS:'pi pi-minus',
|
||||
MINUS_CIRCLE:'pi pi-minus-circle',
|
||||
MOBILE:'pi pi-mobile',
|
||||
MONEY_BILL:'pi pi-money-bill',
|
||||
MOON:'pi pi-moon',
|
||||
PALETTE:'pi pi-palette',
|
||||
PAPERCLIP:'pi pi-paperclip',
|
||||
PAUSE:'pi pi-pause',
|
||||
PAYPAL:'pi pi-paypal',
|
||||
PENCIL:'pi pi-pencil',
|
||||
PERCENTAGE:'pi pi-percentage',
|
||||
PHONE:'pi pi-phone',
|
||||
PLAY:'pi pi-play',
|
||||
PLUS:'pi pi-plus',
|
||||
PLUS_CIRCLE:'pi pi-plus-circle',
|
||||
POUND:'pi pi-pound',
|
||||
POWER_OFF:'pi pi-power-off',
|
||||
PRIME:'pi pi-prime',
|
||||
PRINT:'pi pi-print',
|
||||
QRCODE:'pi pi-qrcode',
|
||||
QUESTION:'pi pi-question',
|
||||
QUESTION_CIRCLE:'pi pi-question-circle',
|
||||
REDDIT:'pi pi-reddit',
|
||||
REFRESH:'pi pi-refresh',
|
||||
REPLAY:'pi pi-replay',
|
||||
REPLY:'pi pi-reply',
|
||||
SAVE:'pi pi-save',
|
||||
SEARCH:'pi pi-search',
|
||||
SEARCH_MINUS:'pi pi-search-minus',
|
||||
SEARCH_PLUS:'pi pi-search-plus',
|
||||
SEND:'pi pi-send',
|
||||
SERVER:'pi pi-server',
|
||||
SHARE_ALT:'pi pi-share-alt',
|
||||
SHIELD:'pi pi-shield',
|
||||
SHOPPING_BAG:'pi pi-shopping-bag',
|
||||
SHOPPING_CART:'pi pi-shopping-cart',
|
||||
SIGN_IN:'pi pi-sign-in',
|
||||
SIGN_OUT:'pi pi-sign-out',
|
||||
SITEMAP:'pi pi-sitemap',
|
||||
SLACK:'pi pi-slack',
|
||||
SLIDERS_H:'pi pi-sliders-h',
|
||||
SLIDERS_V:'pi pi-sliders-v',
|
||||
SORT:'pi pi-sort',
|
||||
SORT_ALPHA_DOWN:'pi pi-sort-alpha-down',
|
||||
SORT_ALPHA_ALT_DOWN:'pi pi-sort-alpha-alt-down',
|
||||
SORT_ALPHA_UP:'pi pi-sort-alpha-up',
|
||||
SORT_ALPHA_ALT_UP:'pi pi-sort-alpha-alt-up',
|
||||
SORT_ALT:'pi pi-sort-alt',
|
||||
SORT_ALT_SLASH:'pi pi-sort-slash',
|
||||
SORT_AMOUNT_DOWN:'pi pi-sort-amount-down',
|
||||
SORT_AMOUNT_DOWN_ALT:'pi pi-sort-amount-down-alt',
|
||||
SORT_AMOUNT_UP:'pi pi-sort-amount-up',
|
||||
SORT_AMOUNT_UP_ALT:'pi pi-sort-amount-up-alt',
|
||||
SORT_DOWN:'pi pi-sort-down',
|
||||
SORT_NUMERIC_DOWN:'pi pi-sort-numeric-down',
|
||||
SORT_NUMERIC_ALT_DOWN:'pi pi-sort-numeric-alt-down',
|
||||
SORT_NUMERIC_UP:'pi pi-sort-numeric-up',
|
||||
SORT_NUMERIC_ALT_UP:'pi pi-sort-numeric-alt-up',
|
||||
SORT_UP:'pi pi-sort-up',
|
||||
SPINNER:'pi pi-spinner',
|
||||
STAR:'pi pi-star',
|
||||
STAR_FILL:'pi pi-star-fill',
|
||||
STEP_BACKWARD:'pi pi-step-backward',
|
||||
STEP_BACKWARD_ALT:'pi pi-step-backward-alt',
|
||||
STEP_FORWARD:'pi pi-step-forward',
|
||||
STEP_FORWARD_ALT:'pi pi-step-forward-alt',
|
||||
STOP:'pi pi-stop',
|
||||
STOP_CIRCLE:'pi pi-stop-circle',
|
||||
SUN:'pi pi-sun',
|
||||
SYNC:'pi pi-sync',
|
||||
TABLE:'pi pi-table',
|
||||
TABLET:'pi pi-tablet',
|
||||
TAG:'pi pi-tag',
|
||||
TAGS:'pi pi-tags',
|
||||
TELEGRAM:'pi pi-telegram',
|
||||
TH_LARGE:'pi pi-th-large',
|
||||
THUMBS_DOWN:'pi pi-thumbs-down',
|
||||
THUMBS_UP:'pi pi-thumbs-up',
|
||||
TICKET:'pi pi-ticket',
|
||||
TIMES:'pi pi-times',
|
||||
TIMES_CIRCLE:'pi pi-times-circle',
|
||||
TRASH:'pi pi-trash',
|
||||
TWITTER:'pi pi-twitter',
|
||||
UNDO:'pi pi-undo',
|
||||
UNLOCK:'pi pi-unlock',
|
||||
UPLOAD:'pi pi-upload',
|
||||
USER:'pi pi-user',
|
||||
USER_EDIT:'pi pi-user-edit',
|
||||
USER_MINUS:'pi pi-user-minus',
|
||||
USER_PLUS:'pi pi-user-plus',
|
||||
USERS:'pi pi-users',
|
||||
VIDEO:'pi pi-video',
|
||||
VIMEO:'pi pi-vimeo',
|
||||
VOLUME_DOWN:'pi pi-volume-down',
|
||||
VOLUME_OFF:'pi pi-volume-off',
|
||||
VOLUME_UP:'pi pi-volume-up',
|
||||
WALLET:'pi pi-wallet',
|
||||
WHATSAPP:'pi pi-whatsapp',
|
||||
WIFI:'pi pi-wifi',
|
||||
WINDOW_MAXIMIZE:'pi pi-window-maximize',
|
||||
WINDOW_MINIMIZE:'pi pi-window-minimize',
|
||||
YOUTUBE:'pi pi-youtube'
|
||||
}
|
||||
ALIGN_CENTER: 'pi pi-align-center',
|
||||
ALIGN_JUSTIFY: 'pi pi-align-justify',
|
||||
ALIGN_LEFT: 'pi pi-align-left',
|
||||
ALIGN_RIGHT: 'pi pi-align-right',
|
||||
AMAZON: 'pi pi-amazon',
|
||||
ANDROID: 'pi pi-android',
|
||||
ANGLE_DOUBLE_DOWN: 'pi pi-angle-double-down',
|
||||
ANGLE_DOUBLE_LEFT: 'pi pi-angle-double-left',
|
||||
ANGLE_DOUBLE_RIGHT: 'pi pi-angle-double-right',
|
||||
ANGLE_DOUBLE_UP: 'pi pi-angle-double-up',
|
||||
ANGLE_DOWN: 'pi pi-angle-down',
|
||||
ANGLE_LEFT: 'pi pi-angle-left',
|
||||
ANGLE_RIGHT: 'pi pi-angle-right',
|
||||
ANGLE_UP: 'pi pi-angle-up',
|
||||
APPLE: 'pi pi-apple',
|
||||
ARROW_CIRCLE_DOWN: 'pi pi-arrow-circle-down',
|
||||
ARROW_CIRCLE_LEFT: 'pi pi-arrow-circle-left',
|
||||
ARROW_CIRCLE_RIGHT: 'pi pi-arrow-circle-right',
|
||||
ARROW_CIRCLE_UP: 'pi pi-arrow-circle-up',
|
||||
ARROW_DOWN: 'pi pi-arrow-down',
|
||||
ARROW_DOWN_LEFT: 'pi pi-arrow-down-left',
|
||||
ARROW_DOWN_RIGHT: 'pi pi-arrow-down-right',
|
||||
ARROW_LEFT: 'pi pi-arrow-left',
|
||||
ARROW_RIGHT: 'pi pi-arrow-right',
|
||||
ARROW_UP: 'pi pi-arrow-up',
|
||||
ARROW_UP_LEFT: 'pi pi-arrow-up-left',
|
||||
ARROW_UP_RIGHT: 'pi pi-arrow-up-right',
|
||||
ARROW_H: 'pi pi-arrow-h',
|
||||
ARROW_V: 'pi pi-arrow-v',
|
||||
AT: 'pi pi-at',
|
||||
BACKWARD: 'pi pi-backward',
|
||||
BAN: 'pi pi-ban',
|
||||
BARS: 'pi pi-bars',
|
||||
BELL: 'pi pi-bell',
|
||||
BOLT: 'pi pi-bolt',
|
||||
BOOK: 'pi pi-book',
|
||||
BOOKMARK: 'pi pi-bookmark',
|
||||
BOOKMARK_FILL: 'pi pi-bookmark-fill',
|
||||
BOX: 'pi pi-box',
|
||||
BRIEFCASE: 'pi pi-briefcase',
|
||||
BUILDING: 'pi pi-building',
|
||||
CALENDAR: 'pi pi-calendar',
|
||||
CALENDAR_MINUS: 'pi pi-calendar-minus',
|
||||
CALENDAR_PLUS: 'pi pi-calendar-plus',
|
||||
CALENDAR_TIMES: 'pi pi-calendar-times',
|
||||
CAMERA: 'pi pi-camera',
|
||||
CAR: 'pi pi-car',
|
||||
CARET_DOWN: 'pi pi-caret-down',
|
||||
CARET_LEFT: 'pi pi-caret-left',
|
||||
CARET_RIGHT: 'pi pi-caret-right',
|
||||
CARET_UP: 'pi pi-caret-up',
|
||||
CHART_BAR: 'pi pi-chart-bar',
|
||||
CHART_LINE: 'pi pi-chart-line',
|
||||
CHART_PIE: 'pi pi-chart-pie',
|
||||
CHECK: 'pi pi-check',
|
||||
CHECK_CIRCLE: 'pi pi-check-circle',
|
||||
CHECK_SQUARE: 'pi pi-check-square',
|
||||
CHEVRON_CIRCLE_DOWN: 'pi pi-chevron-circle-down',
|
||||
CHEVRON_CIRCLE_LEFT: 'pi pi-chevron-circle-left',
|
||||
CHEVRON_CIRCLE_RIGHT: 'pi pi-chevron-circle-right',
|
||||
CHEVRON_CIRCLE_UP: 'pi pi-chevron-circle-up',
|
||||
CHEVRON_DOWN: 'pi pi-chevron-down',
|
||||
CHEVRON_LEFT: 'pi pi-chevron-left',
|
||||
CHEVRON_RIGHT: 'pi pi-chevron-right',
|
||||
CHEVRON_UP: 'pi pi-chevron-up',
|
||||
CIRCLE: 'pi pi-circle',
|
||||
CIRCLE_FILL: 'pi pi-circle-fill',
|
||||
CLOCK: 'pi pi-clock',
|
||||
CLONE: 'pi pi-clone',
|
||||
CLOUD: 'pi pi-cloud',
|
||||
CLOUD_DOWNLOAD: 'pi pi-cloud-download',
|
||||
CLOUD_UPLOAD: 'pi pi-cloud-upload',
|
||||
CODE: 'pi pi-code',
|
||||
COG: 'pi pi-cog',
|
||||
COMMENT: 'pi pi-comment',
|
||||
COMMENTS: 'pi pi-comments',
|
||||
COMPASS: 'pi pi-compass',
|
||||
COPY: 'pi pi-copy',
|
||||
CREDIT_CARD: 'pi pi-credit-card',
|
||||
DATABASE: 'pi pi-database',
|
||||
DESKTOP: 'pi pi-desktop',
|
||||
DIRECTIONS: 'pi pi-directions',
|
||||
DIRECTIONS_ALT: 'pi pi-directions-alt',
|
||||
DISCORD: 'pi pi-discord',
|
||||
DOLLAR: 'pi pi-dollar',
|
||||
DOWNLOAD: 'pi pi-download',
|
||||
EJECT: 'pi pi-eject',
|
||||
ELLIPSIS_H: 'pi pi-ellipsis-h',
|
||||
ELLIPSIS_V: 'pi pi-ellipsis-v',
|
||||
ENVELOPE: 'pi pi-envelope',
|
||||
EURO: 'pi pi-euro',
|
||||
EXCLAMATION_CIRCLE: 'pi pi-exclamation-circle',
|
||||
EXCLAMATION_TRIANGLE: 'pi pi-exclamation-triangle',
|
||||
EXTERNAL_LINK: 'pi pi-external-link',
|
||||
EYE: 'pi pi-eye',
|
||||
EYE_SLASH: 'pi pi-eye-slash',
|
||||
FACEBOOK: 'pi pi-facebook',
|
||||
FAST_BACKWARD: 'pi pi-fast-backward',
|
||||
FAST_FORWARD: 'pi pi-fast-forward',
|
||||
FILE: 'pi pi-file',
|
||||
FILE_EXCEL: 'pi pi-file-excel',
|
||||
FILE_PDF: 'pi pi-file-pdf',
|
||||
FILTER: 'pi pi-filter',
|
||||
FILTER_FILL: 'pi pi-filter-fill',
|
||||
FILTER_SLASH: 'pi pi-filter-slash',
|
||||
FLAG: 'pi pi-flag',
|
||||
FLAG_FILL: 'pi pi-flag-fill',
|
||||
FOLDER: 'pi pi-folder',
|
||||
FOLDER_OPEN: 'pi pi-folder-open',
|
||||
FORWARD: 'pi pi-forward',
|
||||
GITHUB: 'pi pi-github',
|
||||
GLOBE: 'pi pi-globe',
|
||||
GOOGLE: 'pi pi-google',
|
||||
HASHTAG: 'pi pi-hashtag',
|
||||
HEART: 'pi pi-heart',
|
||||
HEART_FILL: 'pi pi-heart-fill',
|
||||
HISTORY: 'pi pi-history',
|
||||
HOME: 'pi pi-home',
|
||||
ID_CARD: 'pi pi-id-card',
|
||||
IMAGE: 'pi pi-image',
|
||||
IMAGES: 'pi pi-images',
|
||||
INBOX: 'pi pi-inbox',
|
||||
INFO: 'pi pi-info',
|
||||
INFO_CIRCLE: 'pi pi-info-circle',
|
||||
INSTAGRAM: 'pi pi-instagram',
|
||||
KEY: 'pi pi-key',
|
||||
LINK: 'pi pi-link',
|
||||
LINKEDIN: 'pi pi-linkedin',
|
||||
LIST: 'pi pi-list',
|
||||
LOCK: 'pi pi-lock',
|
||||
LOCK_OPEN: 'pi pi-lock-open',
|
||||
MAP: 'pi pi-map',
|
||||
MAP_MARKER: 'pi pi-map-marker',
|
||||
MICROSOFT: 'pi pi-microsoft',
|
||||
MINUS: 'pi pi-minus',
|
||||
MINUS_CIRCLE: 'pi pi-minus-circle',
|
||||
MOBILE: 'pi pi-mobile',
|
||||
MONEY_BILL: 'pi pi-money-bill',
|
||||
MOON: 'pi pi-moon',
|
||||
PALETTE: 'pi pi-palette',
|
||||
PAPERCLIP: 'pi pi-paperclip',
|
||||
PAUSE: 'pi pi-pause',
|
||||
PAYPAL: 'pi pi-paypal',
|
||||
PENCIL: 'pi pi-pencil',
|
||||
PERCENTAGE: 'pi pi-percentage',
|
||||
PHONE: 'pi pi-phone',
|
||||
PLAY: 'pi pi-play',
|
||||
PLUS: 'pi pi-plus',
|
||||
PLUS_CIRCLE: 'pi pi-plus-circle',
|
||||
POUND: 'pi pi-pound',
|
||||
POWER_OFF: 'pi pi-power-off',
|
||||
PRIME: 'pi pi-prime',
|
||||
PRINT: 'pi pi-print',
|
||||
QRCODE: 'pi pi-qrcode',
|
||||
QUESTION: 'pi pi-question',
|
||||
QUESTION_CIRCLE: 'pi pi-question-circle',
|
||||
REDDIT: 'pi pi-reddit',
|
||||
REFRESH: 'pi pi-refresh',
|
||||
REPLAY: 'pi pi-replay',
|
||||
REPLY: 'pi pi-reply',
|
||||
SAVE: 'pi pi-save',
|
||||
SEARCH: 'pi pi-search',
|
||||
SEARCH_MINUS: 'pi pi-search-minus',
|
||||
SEARCH_PLUS: 'pi pi-search-plus',
|
||||
SEND: 'pi pi-send',
|
||||
SERVER: 'pi pi-server',
|
||||
SHARE_ALT: 'pi pi-share-alt',
|
||||
SHIELD: 'pi pi-shield',
|
||||
SHOPPING_BAG: 'pi pi-shopping-bag',
|
||||
SHOPPING_CART: 'pi pi-shopping-cart',
|
||||
SIGN_IN: 'pi pi-sign-in',
|
||||
SIGN_OUT: 'pi pi-sign-out',
|
||||
SITEMAP: 'pi pi-sitemap',
|
||||
SLACK: 'pi pi-slack',
|
||||
SLIDERS_H: 'pi pi-sliders-h',
|
||||
SLIDERS_V: 'pi pi-sliders-v',
|
||||
SORT: 'pi pi-sort',
|
||||
SORT_ALPHA_DOWN: 'pi pi-sort-alpha-down',
|
||||
SORT_ALPHA_ALT_DOWN: 'pi pi-sort-alpha-alt-down',
|
||||
SORT_ALPHA_UP: 'pi pi-sort-alpha-up',
|
||||
SORT_ALPHA_ALT_UP: 'pi pi-sort-alpha-alt-up',
|
||||
SORT_ALT: 'pi pi-sort-alt',
|
||||
SORT_ALT_SLASH: 'pi pi-sort-slash',
|
||||
SORT_AMOUNT_DOWN: 'pi pi-sort-amount-down',
|
||||
SORT_AMOUNT_DOWN_ALT: 'pi pi-sort-amount-down-alt',
|
||||
SORT_AMOUNT_UP: 'pi pi-sort-amount-up',
|
||||
SORT_AMOUNT_UP_ALT: 'pi pi-sort-amount-up-alt',
|
||||
SORT_DOWN: 'pi pi-sort-down',
|
||||
SORT_NUMERIC_DOWN: 'pi pi-sort-numeric-down',
|
||||
SORT_NUMERIC_ALT_DOWN: 'pi pi-sort-numeric-alt-down',
|
||||
SORT_NUMERIC_UP: 'pi pi-sort-numeric-up',
|
||||
SORT_NUMERIC_ALT_UP: 'pi pi-sort-numeric-alt-up',
|
||||
SORT_UP: 'pi pi-sort-up',
|
||||
SPINNER: 'pi pi-spinner',
|
||||
STAR: 'pi pi-star',
|
||||
STAR_FILL: 'pi pi-star-fill',
|
||||
STEP_BACKWARD: 'pi pi-step-backward',
|
||||
STEP_BACKWARD_ALT: 'pi pi-step-backward-alt',
|
||||
STEP_FORWARD: 'pi pi-step-forward',
|
||||
STEP_FORWARD_ALT: 'pi pi-step-forward-alt',
|
||||
STOP: 'pi pi-stop',
|
||||
STOP_CIRCLE: 'pi pi-stop-circle',
|
||||
SUN: 'pi pi-sun',
|
||||
SYNC: 'pi pi-sync',
|
||||
TABLE: 'pi pi-table',
|
||||
TABLET: 'pi pi-tablet',
|
||||
TAG: 'pi pi-tag',
|
||||
TAGS: 'pi pi-tags',
|
||||
TELEGRAM: 'pi pi-telegram',
|
||||
TH_LARGE: 'pi pi-th-large',
|
||||
THUMBS_DOWN: 'pi pi-thumbs-down',
|
||||
THUMBS_UP: 'pi pi-thumbs-up',
|
||||
TICKET: 'pi pi-ticket',
|
||||
TIMES: 'pi pi-times',
|
||||
TIMES_CIRCLE: 'pi pi-times-circle',
|
||||
TRASH: 'pi pi-trash',
|
||||
TWITTER: 'pi pi-twitter',
|
||||
UNDO: 'pi pi-undo',
|
||||
UNLOCK: 'pi pi-unlock',
|
||||
UPLOAD: 'pi pi-upload',
|
||||
USER: 'pi pi-user',
|
||||
USER_EDIT: 'pi pi-user-edit',
|
||||
USER_MINUS: 'pi pi-user-minus',
|
||||
USER_PLUS: 'pi pi-user-plus',
|
||||
USERS: 'pi pi-users',
|
||||
VIDEO: 'pi pi-video',
|
||||
VIMEO: 'pi pi-vimeo',
|
||||
VOLUME_DOWN: 'pi pi-volume-down',
|
||||
VOLUME_OFF: 'pi pi-volume-off',
|
||||
VOLUME_UP: 'pi pi-volume-up',
|
||||
WALLET: 'pi pi-wallet',
|
||||
WHATSAPP: 'pi pi-whatsapp',
|
||||
WIFI: 'pi pi-wifi',
|
||||
WINDOW_MAXIMIZE: 'pi pi-window-maximize',
|
||||
WINDOW_MINIMIZE: 'pi pi-window-minimize',
|
||||
YOUTUBE: 'pi pi-youtube'
|
||||
};
|
||||
|
||||
export default PrimeIcons;
|
|
@ -39,7 +39,7 @@ export interface AutoCompleteItemSelectEvent {
|
|||
/**
|
||||
* @extends AutoCompleteItemSelectEvent
|
||||
*/
|
||||
export interface AutoCompleteItemUnselectEvent extends AutoCompleteItemSelectEvent { }
|
||||
export interface AutoCompleteItemUnselectEvent extends AutoCompleteItemSelectEvent {}
|
||||
|
||||
export interface AutoCompleteDropdownClickEvent {
|
||||
/**
|
||||
|
@ -202,6 +202,11 @@ export interface AutoCompleteProps {
|
|||
* Default value is true.
|
||||
*/
|
||||
autoOptionFocus?: boolean | undefined;
|
||||
/**
|
||||
* When enabled, the focused option is selected.
|
||||
* Default value is false.
|
||||
*/
|
||||
selectOnFocus?: boolean | undefined;
|
||||
/**
|
||||
* Locale to use in searching. The default locale is the host environment's current locale.
|
||||
*/
|
||||
|
@ -233,11 +238,11 @@ export interface AutoCompleteProps {
|
|||
/**
|
||||
* Defines a string value that labels an interactive element.
|
||||
*/
|
||||
"aria-label"?: string | undefined;
|
||||
'aria-label'?: string | undefined;
|
||||
/**
|
||||
* Identifier of the underlying input element.
|
||||
*/
|
||||
"aria-labelledby"?: string | undefined;
|
||||
'aria-labelledby'?: string | undefined;
|
||||
}
|
||||
|
||||
export interface AutoCompleteSlots {
|
||||
|
@ -374,17 +379,17 @@ export declare type AutoCompleteEmits = {
|
|||
* Callback to invoke on value change.
|
||||
* @param {AutoCompleteChangeEvent} event - Custom change event.
|
||||
*/
|
||||
'change': (event: AutoCompleteChangeEvent) => void;
|
||||
change: (event: AutoCompleteChangeEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when the component receives focus.
|
||||
* @param {Event} event - Browser event.
|
||||
*/
|
||||
'focus': (event: Event) => void;
|
||||
focus: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke when the component loses focus.
|
||||
* @param {Event} event - Browser event.
|
||||
*/
|
||||
'blur': (event: Event) => void;
|
||||
blur: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke when a suggestion is selected.
|
||||
* @param {AutoCompleteItemSelectEvent} event - Custom item select event.
|
||||
|
@ -403,12 +408,12 @@ export declare type AutoCompleteEmits = {
|
|||
/**
|
||||
* Callback to invoke when input is cleared by the user.
|
||||
*/
|
||||
'clear': () => void;
|
||||
clear: () => void;
|
||||
/**
|
||||
* Callback to invoke to search for suggestions.
|
||||
* @param {AutoCompleteCompleteEvent} event - Custom complete event.
|
||||
*/
|
||||
'complete': (event: AutoCompleteCompleteEvent) => void;
|
||||
complete: (event: AutoCompleteCompleteEvent) => void;
|
||||
/**
|
||||
* Callback to invoke before the overlay is shown.
|
||||
*/
|
||||
|
@ -420,18 +425,18 @@ export declare type AutoCompleteEmits = {
|
|||
/**
|
||||
* Callback to invoke when the overlay is shown.
|
||||
*/
|
||||
'show': () => void;
|
||||
show: () => void;
|
||||
/**
|
||||
* Callback to invoke when the overlay is hidden.
|
||||
*/
|
||||
'hide': () => void;
|
||||
}
|
||||
hide: () => void;
|
||||
};
|
||||
|
||||
declare class AutoComplete extends ClassComponent<AutoCompleteProps, AutoCompleteSlots, AutoCompleteEmits> { }
|
||||
declare class AutoComplete extends ClassComponent<AutoCompleteProps, AutoCompleteSlots, AutoCompleteEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
AutoComplete: GlobalComponentConstructor<AutoComplete>
|
||||
AutoComplete: GlobalComponentConstructor<AutoComplete>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,7 +446,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [AutoComplete](https://www.primefaces.org/primevue/showcase/#/autocomplete)
|
||||
* - [AutoComplete](https://www.primefaces.org/primevue/autocomplete)
|
||||
*
|
||||
*/
|
||||
export default AutoComplete;
|
||||
|
|
|
@ -20,12 +20,12 @@ describe('AutoComplete.vue', () => {
|
|||
data() {
|
||||
return {
|
||||
countries: [
|
||||
{"name": "Afghanistan", "code": "AF"},
|
||||
{"name": "Bahrain", "code": "BH"},
|
||||
{"name": "Chile", "code": "CL"},
|
||||
{"name": "Denmark", "code": "DK"}
|
||||
{ name: 'Afghanistan', code: 'AF' },
|
||||
{ name: 'Bahrain', code: 'BH' },
|
||||
{ name: 'Chile', code: 'CL' },
|
||||
{ name: 'Denmark', code: 'DK' }
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -38,18 +38,16 @@ describe('AutoComplete.vue', () => {
|
|||
});
|
||||
|
||||
it('search copmlete', async () => {
|
||||
const event = {'target': { 'value': 'b' }};
|
||||
const event = { target: { value: 'b' } };
|
||||
|
||||
wrapper.vm.onInput(event);
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
wrapper.vm.search(event , event.target.value, 'input');
|
||||
wrapper.vm.search(event, event.target.value, 'input');
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
await wrapper.setProps({
|
||||
suggestions: [
|
||||
{"name": "Bahrain", "code": "BH"}
|
||||
]
|
||||
suggestions: [{ name: 'Bahrain', code: 'BH' }]
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-autocomplete-items').exists()).toBe(true);
|
||||
|
|
|
@ -1,50 +1,127 @@
|
|||
<template>
|
||||
<div ref="container" :class="containerClass" @click="onContainerClick">
|
||||
<input v-if="!multiple" ref="focusInput" :id="inputId" type="text" :style="inputStyle" :class="inputStyleClass" :value="inputValue" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1" :disabled="disabled" autocomplete="off"
|
||||
role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="listbox" aria-autocomplete="list" :aria-expanded="overlayVisible" :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @input="onInput" @change="onChange" v-bind="inputProps" />
|
||||
<ul v-if="multiple" ref="multiContainer" :class="multiContainerClass" tabindex="-1" role="listbox" aria-orientation="horizontal" :aria-activedescendant="focused ? focusedMultipleOptionId : undefined"
|
||||
@focus="onMultipleContainerFocus" @blur="onMultipleContainerBlur" @keydown="onMultipleContainerKeyDown">
|
||||
<li v-for="(option, i) of modelValue" :key="i" :id="id + '_multiple_option_' + i" :class="['p-autocomplete-token', {'p-focus': focusedMultipleOptionIndex === i}]"
|
||||
role="option" :aria-label="getOptionLabel(option)" :aria-selected="true" :aria-setsize="modelValue.length" :aria-posinset="i + 1">
|
||||
<input
|
||||
v-if="!multiple"
|
||||
ref="focusInput"
|
||||
:id="inputId"
|
||||
type="text"
|
||||
:style="inputStyle"
|
||||
:class="inputStyleClass"
|
||||
:value="inputValue"
|
||||
:placeholder="placeholder"
|
||||
:tabindex="!disabled ? tabindex : -1"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
role="combobox"
|
||||
:aria-label="ariaLabel"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
aria-haspopup="listbox"
|
||||
aria-autocomplete="list"
|
||||
:aria-expanded="overlayVisible"
|
||||
:aria-controls="id + '_list'"
|
||||
:aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@keydown="onKeyDown"
|
||||
@input="onInput"
|
||||
@change="onChange"
|
||||
v-bind="inputProps"
|
||||
/>
|
||||
<ul
|
||||
v-if="multiple"
|
||||
ref="multiContainer"
|
||||
:class="multiContainerClass"
|
||||
tabindex="-1"
|
||||
role="listbox"
|
||||
aria-orientation="horizontal"
|
||||
:aria-activedescendant="focused ? focusedMultipleOptionId : undefined"
|
||||
@focus="onMultipleContainerFocus"
|
||||
@blur="onMultipleContainerBlur"
|
||||
@keydown="onMultipleContainerKeyDown"
|
||||
>
|
||||
<li
|
||||
v-for="(option, i) of modelValue"
|
||||
:key="i"
|
||||
:id="id + '_multiple_option_' + i"
|
||||
:class="['p-autocomplete-token', { 'p-focus': focusedMultipleOptionIndex === i }]"
|
||||
role="option"
|
||||
:aria-label="getOptionLabel(option)"
|
||||
:aria-selected="true"
|
||||
:aria-setsize="modelValue.length"
|
||||
:aria-posinset="i + 1"
|
||||
>
|
||||
<slot name="chip" :value="option">
|
||||
<span class="p-autocomplete-token-label">{{getOptionLabel(option)}}</span>
|
||||
<span class="p-autocomplete-token-label">{{ getOptionLabel(option) }}</span>
|
||||
</slot>
|
||||
<span class="p-autocomplete-token-icon pi pi-times-circle" @click="removeOption($event, i)" aria-hidden="true"></span>
|
||||
</li>
|
||||
<li class="p-autocomplete-input-token" role="option">
|
||||
<input ref="focusInput" :id="inputId" type="text" :style="inputStyle" :class="inputClass" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1" :disabled="disabled" autocomplete="off"
|
||||
role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="listbox" aria-autocomplete="list" :aria-expanded="overlayVisible" :aria-controls="id + '_list'" :aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@focus="onFocus" @blur="onBlur" @keydown="onKeyDown" @input="onInput" @change="onChange" v-bind="inputProps" />
|
||||
<input
|
||||
ref="focusInput"
|
||||
:id="inputId"
|
||||
type="text"
|
||||
:style="inputStyle"
|
||||
:class="inputClass"
|
||||
:placeholder="placeholder"
|
||||
:tabindex="!disabled ? tabindex : -1"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
role="combobox"
|
||||
:aria-label="ariaLabel"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
aria-haspopup="listbox"
|
||||
aria-autocomplete="list"
|
||||
:aria-expanded="overlayVisible"
|
||||
:aria-controls="id + '_list'"
|
||||
:aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@keydown="onKeyDown"
|
||||
@input="onInput"
|
||||
@change="onChange"
|
||||
v-bind="inputProps"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
<i v-if="searching" :class="loadingIconClass" aria-hidden="true"></i>
|
||||
<Button v-if="dropdown" ref="dropdownButton" type="button" icon="pi pi-chevron-down" class="p-autocomplete-dropdown" tabindex="-1" :disabled="disabled" aria-hidden="true" @click="onDropdownClick" />
|
||||
<span role="status" aria-live="polite" class="p-hidden-accessible">
|
||||
{{searchResultMessageText}}
|
||||
{{ searchResultMessageText }}
|
||||
</span>
|
||||
<Portal :appendTo="appendTo">
|
||||
<transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
|
||||
<div v-if="overlayVisible" :ref="overlayRef" :class="panelStyleClass" :style="{...panelStyle, 'max-height': virtualScrollerDisabled ? scrollHeight : ''}" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="panelProps">
|
||||
<div v-if="overlayVisible" :ref="overlayRef" :class="panelStyleClass" :style="{ ...panelStyle, 'max-height': virtualScrollerDisabled ? scrollHeight : '' }" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="panelProps">
|
||||
<slot name="header" :value="modelValue" :suggestions="visibleOptions"></slot>
|
||||
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="{'height': scrollHeight}" :items="visibleOptions" :tabindex="-1" :disabled="virtualScrollerDisabled">
|
||||
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="{ height: scrollHeight }" :items="visibleOptions" :tabindex="-1" :disabled="virtualScrollerDisabled">
|
||||
<template v-slot:content="{ styleClass, contentRef, items, getItemOptions, contentStyle, itemSize }">
|
||||
<ul :ref="(el) => listRef(el, contentRef)" :id="id + '_list'" :class="['p-autocomplete-items', styleClass]" :style="contentStyle" role="listbox">
|
||||
<template v-for="(option, i) of items" :key="getOptionRenderKey(option, getOptionIndex(i, getItemOptions))">
|
||||
<li v-if="isOptionGroup(option)" :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}" class="p-autocomplete-item-group" role="option">
|
||||
<slot name="optiongroup" :option="option.optionGroup" :item="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(option.optionGroup)}}</slot>
|
||||
<li v-if="isOptionGroup(option)" :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{ height: itemSize ? itemSize + 'px' : undefined }" class="p-autocomplete-item-group" role="option">
|
||||
<slot name="optiongroup" :option="option.optionGroup" :item="option.optionGroup" :index="getOptionIndex(i, getItemOptions)">{{ getOptionGroupLabel(option.optionGroup) }}</slot>
|
||||
</li>
|
||||
<li v-else v-ripple :id="id + '_' + getOptionIndex(i, getItemOptions)" :style="{height: itemSize ? itemSize + 'px' : undefined}"
|
||||
:class="['p-autocomplete-item', {'p-highlight': isSelected(option), 'p-focus': focusedOptionIndex === getOptionIndex(i, getItemOptions), 'p-disabled': isOptionDisabled(option)}]"
|
||||
role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" :aria-disabled="isOptionDisabled(option)" :aria-setsize="ariaSetSize" :aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
|
||||
@click="onOptionSelect($event, option)" @mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))">
|
||||
<slot v-if="$slots.option" name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot>
|
||||
<slot v-else name="item" :item="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot> <!--TODO: Deprecated since v3.16.0-->
|
||||
<li
|
||||
v-else
|
||||
:id="id + '_' + getOptionIndex(i, getItemOptions)"
|
||||
v-ripple
|
||||
:style="{ height: itemSize ? itemSize + 'px' : undefined }"
|
||||
:class="['p-autocomplete-item', { 'p-highlight': isSelected(option), 'p-focus': focusedOptionIndex === getOptionIndex(i, getItemOptions), 'p-disabled': isOptionDisabled(option) }]"
|
||||
role="option"
|
||||
:aria-label="getOptionLabel(option)"
|
||||
:aria-selected="isSelected(option)"
|
||||
:aria-disabled="isOptionDisabled(option)"
|
||||
:aria-setsize="ariaSetSize"
|
||||
:aria-posinset="getAriaPosInset(getOptionIndex(i, getItemOptions))"
|
||||
@click="onOptionSelect($event, option)"
|
||||
@mousemove="onOptionMouseMove($event, getOptionIndex(i, getItemOptions))"
|
||||
>
|
||||
<slot v-if="$slots.option" name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{ getOptionLabel(option) }}</slot>
|
||||
<slot v-else name="item" :item="option" :index="getOptionIndex(i, getItemOptions)">{{ getOptionLabel(option) }}</slot>
|
||||
<!--TODO: Deprecated since v3.16.0-->
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<span role="status" aria-live="polite" class="p-hidden-accessible">
|
||||
{{selectedMessageText}}
|
||||
{{ selectedMessageText }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="$slots.loader" v-slot:loader="{ options }">
|
||||
|
@ -59,7 +136,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {ConnectedOverlayScrollHandler,UniqueComponentId,ObjectUtils,DomHandler,ZIndexUtils} from 'primevue/utils';
|
||||
import { ConnectedOverlayScrollHandler, UniqueComponentId, ObjectUtils, DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import Button from 'primevue/button';
|
||||
import Ripple from 'primevue/ripple';
|
||||
|
@ -75,8 +152,9 @@ export default {
|
|||
type: Array,
|
||||
default: null
|
||||
},
|
||||
field: { // TODO: Deprecated since v3.16.0
|
||||
type: [String,Function],
|
||||
field: {
|
||||
// TODO: Deprecated since v3.16.0
|
||||
type: [String, Function],
|
||||
default: null
|
||||
},
|
||||
optionLabel: null,
|
||||
|
@ -95,7 +173,8 @@ export default {
|
|||
type: String,
|
||||
default: 'blank'
|
||||
},
|
||||
autoHighlight: { // TODO: Deprecated since v3.16.0
|
||||
autoHighlight: {
|
||||
// TODO: Deprecated since v3.16.0. Use selectOnFocus property instead.
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
@ -135,13 +214,34 @@ export default {
|
|||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
inputId: String,
|
||||
inputStyle: null,
|
||||
inputClass: null,
|
||||
inputProps: null,
|
||||
panelStyle: null,
|
||||
panelClass: null,
|
||||
panelProps: null,
|
||||
inputId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
inputClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
panelStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
panelClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
panelProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: 'pi pi-spinner'
|
||||
|
@ -154,6 +254,10 @@ export default {
|
|||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selectOnFocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
searchLocale: {
|
||||
type: String,
|
||||
default: undefined
|
||||
|
@ -193,18 +297,16 @@ export default {
|
|||
overlay: null,
|
||||
virtualScroller: null,
|
||||
searchTimeout: null,
|
||||
selectOnFocus: false,
|
||||
focusOnHover: false,
|
||||
dirty: false,
|
||||
data() {
|
||||
return {
|
||||
id: UniqueComponentId(),
|
||||
focused: false,
|
||||
focusedOptionIndex: -1,
|
||||
focusedMultipleOptionIndex: -1,
|
||||
overlayVisible: false,
|
||||
searching: false
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
suggestions() {
|
||||
|
@ -218,8 +320,6 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
this.id = this.$attrs.id || this.id;
|
||||
|
||||
this.autoUpdateModel();
|
||||
},
|
||||
updated() {
|
||||
|
@ -243,7 +343,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
getOptionIndex(index, fn) {
|
||||
return this.virtualScrollerDisabled ? index : (fn && fn(index)['index']);
|
||||
return this.virtualScrollerDisabled ? index : fn && fn(index)['index'];
|
||||
},
|
||||
getOptionLabel(option) {
|
||||
return this.field || this.optionLabel ? ObjectUtils.resolveFieldData(option, this.field || this.optionLabel) : option;
|
||||
|
@ -267,15 +367,15 @@ export default {
|
|||
return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren);
|
||||
},
|
||||
getAriaPosInset(index) {
|
||||
return (this.optionGroupLabel ? index - this.visibleOptions.slice(0, index).filter(option => this.isOptionGroup(option)).length : index) + 1;
|
||||
return (this.optionGroupLabel ? index - this.visibleOptions.slice(0, index).filter((option) => this.isOptionGroup(option)).length : index) + 1;
|
||||
},
|
||||
show(isFocus) {
|
||||
this.$emit('before-show');
|
||||
this.dirty = true;
|
||||
this.overlayVisible = true;
|
||||
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
|
||||
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1;
|
||||
|
||||
isFocus && this.$refs.focusInput.focus();
|
||||
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||
},
|
||||
hide(isFocus) {
|
||||
const _hide = () => {
|
||||
|
@ -284,10 +384,12 @@ export default {
|
|||
this.overlayVisible = false;
|
||||
this.focusedOptionIndex = -1;
|
||||
|
||||
isFocus && this.$refs.focusInput.focus();
|
||||
}
|
||||
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||
};
|
||||
|
||||
setTimeout(() => { _hide() }, 0); // For ScreenReaders
|
||||
setTimeout(() => {
|
||||
_hide();
|
||||
}, 0); // For ScreenReaders
|
||||
},
|
||||
onFocus(event) {
|
||||
if (!this.dirty && this.completeOnFocus) {
|
||||
|
@ -371,6 +473,7 @@ export default {
|
|||
}
|
||||
|
||||
let query = event.target.value;
|
||||
|
||||
if (!this.multiple) {
|
||||
this.updateModel(event, query);
|
||||
}
|
||||
|
@ -378,16 +481,14 @@ export default {
|
|||
if (query.length === 0) {
|
||||
this.hide();
|
||||
this.$emit('clear');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (query.length >= this.minLength) {
|
||||
this.focusedOptionIndex = -1;
|
||||
|
||||
this.searchTimeout = setTimeout(() => {
|
||||
this.search(event, query, 'input');
|
||||
}, this.delay);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
@ -396,8 +497,8 @@ export default {
|
|||
if (this.forceSelection) {
|
||||
let valid = false;
|
||||
|
||||
if (this.visibleOptions) {
|
||||
const matchedValue = this.visibleOptions.find(option => this.isOptionMatched(option, event.target.value));
|
||||
if (this.visibleOptions) {
|
||||
const matchedValue = this.visibleOptions.find((option) => this.isOptionMatched(option, event.target.value));
|
||||
|
||||
if (matchedValue !== undefined) {
|
||||
valid = true;
|
||||
|
@ -443,7 +544,7 @@ export default {
|
|||
}
|
||||
|
||||
if (!this.overlay || !this.overlay.contains(event.target)) {
|
||||
this.$refs.focusInput.focus();
|
||||
DomHandler.focus(this.$refs.focusInput);
|
||||
}
|
||||
},
|
||||
onDropdownClick(event) {
|
||||
|
@ -451,20 +552,17 @@ export default {
|
|||
|
||||
if (this.overlayVisible) {
|
||||
this.hide(true);
|
||||
}
|
||||
else {
|
||||
this.$refs.focusInput.focus();
|
||||
} else {
|
||||
DomHandler.focus(this.$refs.focusInput);
|
||||
query = this.$refs.focusInput.value;
|
||||
|
||||
if (this.dropdownMode === 'blank')
|
||||
this.search(event, '', 'dropdown');
|
||||
else if (this.dropdownMode === 'current')
|
||||
this.search(event, query, 'dropdown');
|
||||
if (this.dropdownMode === 'blank') this.search(event, '', 'dropdown');
|
||||
else if (this.dropdownMode === 'current') this.search(event, query, 'dropdown');
|
||||
}
|
||||
|
||||
this.$emit('dropdown-click', { originalEvent: event, query });
|
||||
},
|
||||
onOptionSelect(event, option) {
|
||||
onOptionSelect(event, option, isHide = true) {
|
||||
const value = this.getOptionValue(option);
|
||||
|
||||
if (this.multiple) {
|
||||
|
@ -473,14 +571,13 @@ export default {
|
|||
if (!this.isSelected(option)) {
|
||||
this.updateModel(event, [...(this.modelValue || []), value]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.updateModel(event, value);
|
||||
}
|
||||
|
||||
this.$emit('item-select', { originalEvent: event, value: option });
|
||||
|
||||
this.hide(true);
|
||||
isHide && this.hide(true);
|
||||
},
|
||||
onOptionMouseMove(event, index) {
|
||||
if (this.focusOnHover) {
|
||||
|
@ -526,8 +623,7 @@ export default {
|
|||
|
||||
this.overlayVisible && this.hide();
|
||||
event.preventDefault();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.findLastFocusedOptionIndex();
|
||||
|
||||
this.changeFocusedOptionIndex(event, optionIndex);
|
||||
|
@ -537,14 +633,14 @@ export default {
|
|||
},
|
||||
onArrowLeftKey(event) {
|
||||
const target = event.currentTarget;
|
||||
|
||||
this.focusedOptionIndex = -1;
|
||||
|
||||
if (this.multiple) {
|
||||
if (ObjectUtils.isEmpty(target.value) && this.hasSelectedOption) {
|
||||
this.$refs.multiContainer.focus();
|
||||
DomHandler.focus(this.$refs.multiContainer);
|
||||
this.focusedMultipleOptionIndex = this.modelValue.length;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
event.stopPropagation(); // To prevent onArrowLeftKeyOnMultiple method
|
||||
}
|
||||
}
|
||||
|
@ -563,6 +659,7 @@ export default {
|
|||
onEndKey(event) {
|
||||
const target = event.currentTarget;
|
||||
const len = target.value.length;
|
||||
|
||||
target.setSelectionRange(len, len);
|
||||
this.focusedOptionIndex = -1;
|
||||
|
||||
|
@ -579,8 +676,7 @@ export default {
|
|||
onEnterKey(event) {
|
||||
if (!this.overlayVisible) {
|
||||
this.onArrowDownKey(event);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (this.focusedOptionIndex !== -1) {
|
||||
this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]);
|
||||
}
|
||||
|
@ -620,9 +716,9 @@ export default {
|
|||
onArrowRightKeyOnMultiple() {
|
||||
this.focusedMultipleOptionIndex++;
|
||||
|
||||
if (this.focusedMultipleOptionIndex > (this.modelValue.length - 1)) {
|
||||
if (this.focusedMultipleOptionIndex > this.modelValue.length - 1) {
|
||||
this.focusedMultipleOptionIndex = -1;
|
||||
this.$refs.focusInput.focus();
|
||||
DomHandler.focus(this.$refs.focusInput);
|
||||
}
|
||||
},
|
||||
onBackspaceKeyOnMultiple(event) {
|
||||
|
@ -654,10 +750,10 @@ export default {
|
|||
},
|
||||
alignOverlay() {
|
||||
let target = this.multiple ? this.$refs.multiContainer : this.$refs.focusInput;
|
||||
|
||||
if (this.appendTo === 'self') {
|
||||
DomHandler.relativePosition(this.overlay, target);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.overlay.style.minWidth = DomHandler.getOuterWidth(target) + 'px';
|
||||
DomHandler.absolutePosition(this.overlay, target);
|
||||
}
|
||||
|
@ -669,6 +765,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
|
@ -701,6 +798,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', this.resizeListener);
|
||||
}
|
||||
},
|
||||
|
@ -714,13 +812,11 @@ export default {
|
|||
return !this.overlay.contains(event.target) && !this.isInputClicked(event) && !this.isDropdownClicked(event);
|
||||
},
|
||||
isInputClicked(event) {
|
||||
if (this.multiple)
|
||||
return event.target === this.$refs.multiContainer || this.$refs.multiContainer.contains(event.target);
|
||||
else
|
||||
return event.target === this.$refs.focusInput;
|
||||
if (this.multiple) return event.target === this.$refs.multiContainer || this.$refs.multiContainer.contains(event.target);
|
||||
else return event.target === this.$refs.focusInput;
|
||||
},
|
||||
isDropdownClicked(event) {
|
||||
return this.$refs.dropdownButton ? (event.target === this.$refs.dropdownButton || this.$refs.dropdownButton.$el.contains(event.target)) : false;
|
||||
return this.$refs.dropdownButton ? event.target === this.$refs.dropdownButton || this.$refs.dropdownButton.$el.contains(event.target) : false;
|
||||
},
|
||||
isOptionMatched(option, value) {
|
||||
return this.isValidOption(option) && this.getOptionLabel(option).toLocaleLowerCase(this.searchLocale) === value.toLocaleLowerCase(this.searchLocale);
|
||||
|
@ -735,28 +831,32 @@ export default {
|
|||
return ObjectUtils.equals(this.modelValue, this.getOptionValue(option), this.equalityKey);
|
||||
},
|
||||
findFirstOptionIndex() {
|
||||
return this.visibleOptions.findIndex(option => this.isValidOption(option));
|
||||
return this.visibleOptions.findIndex((option) => this.isValidOption(option));
|
||||
},
|
||||
findLastOptionIndex() {
|
||||
return ObjectUtils.findLastIndex(this.visibleOptions, option => this.isValidOption(option));
|
||||
return ObjectUtils.findLastIndex(this.visibleOptions, (option) => this.isValidOption(option));
|
||||
},
|
||||
findNextOptionIndex(index) {
|
||||
const matchedOptionIndex = index < (this.visibleOptions.length - 1) ? this.visibleOptions.slice(index + 1).findIndex(option => this.isValidOption(option)) : -1;
|
||||
const matchedOptionIndex = index < this.visibleOptions.length - 1 ? this.visibleOptions.slice(index + 1).findIndex((option) => this.isValidOption(option)) : -1;
|
||||
|
||||
return matchedOptionIndex > -1 ? matchedOptionIndex + index + 1 : index;
|
||||
},
|
||||
findPrevOptionIndex(index) {
|
||||
const matchedOptionIndex = index > 0 ? ObjectUtils.findLastIndex(this.visibleOptions.slice(0, index), option => this.isValidOption(option)) : -1;
|
||||
const matchedOptionIndex = index > 0 ? ObjectUtils.findLastIndex(this.visibleOptions.slice(0, index), (option) => this.isValidOption(option)) : -1;
|
||||
|
||||
return matchedOptionIndex > -1 ? matchedOptionIndex : index;
|
||||
},
|
||||
findSelectedOptionIndex() {
|
||||
return this.hasSelectedOption ? this.visibleOptions.findIndex(option => this.isValidSelectedOption(option)) : -1;
|
||||
return this.hasSelectedOption ? this.visibleOptions.findIndex((option) => this.isValidSelectedOption(option)) : -1;
|
||||
},
|
||||
findFirstFocusedOptionIndex() {
|
||||
const selectedIndex = this.findSelectedOptionIndex();
|
||||
|
||||
return selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex;
|
||||
},
|
||||
findLastFocusedOptionIndex() {
|
||||
const selectedIndex = this.findSelectedOptionIndex();
|
||||
|
||||
return selectedIndex < 0 ? this.findLastOptionIndex() : selectedIndex;
|
||||
},
|
||||
search(event, query, source) {
|
||||
|
@ -775,12 +875,12 @@ export default {
|
|||
},
|
||||
removeOption(event, index) {
|
||||
const removedOption = this.modelValue[index];
|
||||
const value = this.modelValue.filter((_, i) => i !== index).map(option => this.getOptionValue(option));
|
||||
const value = this.modelValue.filter((_, i) => i !== index).map((option) => this.getOptionValue(option));
|
||||
|
||||
this.updateModel(event, value);
|
||||
this.$emit('item-unselect', { originalEvent: event, value: removedOption });
|
||||
this.dirty = true;
|
||||
this.$refs.focusInput.focus();
|
||||
DomHandler.focus(this.$refs.focusInput);
|
||||
},
|
||||
changeFocusedOptionIndex(event, index) {
|
||||
if (this.focusedOptionIndex !== index) {
|
||||
|
@ -788,17 +888,17 @@ export default {
|
|||
this.scrollInView();
|
||||
|
||||
if (this.selectOnFocus || this.autoHighlight) {
|
||||
this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
|
||||
this.onOptionSelect(event, this.visibleOptions[index], false);
|
||||
}
|
||||
}
|
||||
},
|
||||
scrollInView(index = -1) {
|
||||
const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
|
||||
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
|
||||
|
||||
if (element) {
|
||||
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
|
||||
}
|
||||
else if (!this.virtualScrollerDisabled) {
|
||||
} else if (!this.virtualScrollerDisabled) {
|
||||
setTimeout(() => {
|
||||
this.virtualScroller && this.virtualScroller.scrollToIndex(index !== -1 ? index : this.focusedOptionIndex);
|
||||
}, 0);
|
||||
|
@ -807,8 +907,7 @@ export default {
|
|||
autoUpdateModel() {
|
||||
if ((this.selectOnFocus || this.autoHighlight) && this.autoOptionFocus && !this.hasSelectedOption) {
|
||||
this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
|
||||
const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
|
||||
this.updateModel(null, this.multiple ? [value] : value);
|
||||
this.onOptionSelect(null, this.visibleOptions[this.focusedOptionIndex], false);
|
||||
}
|
||||
},
|
||||
updateModel(event, value) {
|
||||
|
@ -820,7 +919,8 @@ export default {
|
|||
result.push({ optionGroup: option, group: true, index });
|
||||
|
||||
const optionGroupChildren = this.getOptionGroupChildren(option);
|
||||
optionGroupChildren && optionGroupChildren.forEach(o => result.push(o));
|
||||
|
||||
optionGroupChildren && optionGroupChildren.forEach((o) => result.push(o));
|
||||
|
||||
return result;
|
||||
}, []);
|
||||
|
@ -838,47 +938,57 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-autocomplete p-component p-inputwrapper', {
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused,
|
||||
'p-autocomplete-dd': this.dropdown,
|
||||
'p-autocomplete-multiple': this.multiple,
|
||||
'p-inputwrapper-filled': this.modelValue || ObjectUtils.isNotEmpty(this.inputValue),
|
||||
'p-inputwrapper-focus': this.focused,
|
||||
'p-overlay-open': this.overlayVisible
|
||||
}];
|
||||
return [
|
||||
'p-autocomplete p-component p-inputwrapper',
|
||||
{
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused,
|
||||
'p-autocomplete-dd': this.dropdown,
|
||||
'p-autocomplete-multiple': this.multiple,
|
||||
'p-inputwrapper-filled': this.modelValue || ObjectUtils.isNotEmpty(this.inputValue),
|
||||
'p-inputwrapper-focus': this.focused,
|
||||
'p-overlay-open': this.overlayVisible
|
||||
}
|
||||
];
|
||||
},
|
||||
inputStyleClass() {
|
||||
return ['p-autocomplete-input p-inputtext p-component', this.inputClass, {
|
||||
'p-autocomplete-dd-input': this.dropdown
|
||||
}];
|
||||
return [
|
||||
'p-autocomplete-input p-inputtext p-component',
|
||||
this.inputClass,
|
||||
{
|
||||
'p-autocomplete-dd-input': this.dropdown
|
||||
}
|
||||
];
|
||||
},
|
||||
multiContainerClass() {
|
||||
return ['p-autocomplete-multiple-container p-component p-inputtext'];
|
||||
},
|
||||
panelStyleClass() {
|
||||
return ['p-autocomplete-panel p-component', this.panelClass, {
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}];
|
||||
return [
|
||||
'p-autocomplete-panel p-component',
|
||||
this.panelClass,
|
||||
{
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
},
|
||||
loadingIconClass() {
|
||||
return ['p-autocomplete-loader pi-spin', this.loadingIcon];
|
||||
},
|
||||
visibleOptions() {
|
||||
return this.optionGroupLabel ? this.flatOptions(this.suggestions) : (this.suggestions || []);
|
||||
return this.optionGroupLabel ? this.flatOptions(this.suggestions) : this.suggestions || [];
|
||||
},
|
||||
inputValue() {
|
||||
if (this.modelValue) {
|
||||
if (typeof this.modelValue === 'object') {
|
||||
const label = this.getOptionLabel(this.modelValue);
|
||||
|
||||
return label != null ? label : this.modelValue;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return this.modelValue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
@ -906,6 +1016,9 @@ export default {
|
|||
selectedMessageText() {
|
||||
return this.hasSelectedOption ? this.selectionMessageText.replaceAll('{0}', this.multiple ? this.modelValue.length : '1') : this.emptySelectionMessageText;
|
||||
},
|
||||
id() {
|
||||
return this.$attrs.id || UniqueComponentId();
|
||||
},
|
||||
focusedOptionId() {
|
||||
return this.focusedOptionIndex !== -1 ? `${this.id}_${this.focusedOptionIndex}` : null;
|
||||
},
|
||||
|
@ -913,21 +1026,21 @@ export default {
|
|||
return this.focusedMultipleOptionIndex !== -1 ? `${this.id}_multiple_option_${this.focusedMultipleOptionIndex}` : null;
|
||||
},
|
||||
ariaSetSize() {
|
||||
return this.visibleOptions.filter(option => !this.isOptionGroup(option)).length;
|
||||
return this.visibleOptions.filter((option) => !this.isOptionGroup(option)).length;
|
||||
},
|
||||
virtualScrollerDisabled() {
|
||||
return !this.virtualScrollerOptions;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'Button': Button,
|
||||
'VirtualScroller': VirtualScroller,
|
||||
'Portal': Portal
|
||||
Button: Button,
|
||||
VirtualScroller: VirtualScroller,
|
||||
Portal: Portal
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
ripple: Ripple
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -939,7 +1052,7 @@ export default {
|
|||
.p-autocomplete-loader {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -.5rem;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
.p-autocomplete-dd .p-autocomplete-input {
|
||||
|
@ -949,13 +1062,13 @@ export default {
|
|||
|
||||
.p-autocomplete-dd .p-autocomplete-input,
|
||||
.p-autocomplete-dd .p-autocomplete-multiple-container {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.p-autocomplete-dd .p-autocomplete-dropdown {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0px;
|
||||
}
|
||||
|
||||
.p-autocomplete .p-autocomplete-panel {
|
||||
|
|
|
@ -44,13 +44,13 @@ export declare type AvatarEmits = {
|
|||
* Triggered when an error occurs while loading an image file.
|
||||
*/
|
||||
error: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
declare class Avatar extends ClassComponent<AvatarProps, AvatarSlots, AvatarEmits> { }
|
||||
declare class Avatar extends ClassComponent<AvatarProps, AvatarSlots, AvatarEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Avatar: GlobalComponentConstructor<Avatar>
|
||||
Avatar: GlobalComponentConstructor<Avatar>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Avatar](https://www.primefaces.org/primevue/showcase/#/avatar)
|
||||
* - [Avatar](https://www.primefaces.org/primevue/avatar)
|
||||
*
|
||||
*/
|
||||
export default Avatar;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div :class="containerClass">
|
||||
<slot>
|
||||
<span class="p-avatar-text" v-if="label">{{label}}</span>
|
||||
<span :class="iconClass" v-else-if="icon"></span>
|
||||
<img :src="image" v-else-if="image" @error="onError">
|
||||
<span v-if="label" class="p-avatar-text">{{ label }}</span>
|
||||
<span v-else-if="icon" :class="iconClass"></span>
|
||||
<img v-else-if="image" :src="image" @error="onError" />
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -11,6 +11,7 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'Avatar',
|
||||
emits: ['error'],
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
|
@ -30,7 +31,7 @@ export default {
|
|||
},
|
||||
shape: {
|
||||
type: String,
|
||||
default: "square"
|
||||
default: 'square'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -40,18 +41,21 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-avatar p-component', {
|
||||
'p-avatar-image': this.image != null,
|
||||
'p-avatar-circle': this.shape === 'circle',
|
||||
'p-avatar-lg': this.size === 'large',
|
||||
'p-avatar-xl': this.size === 'xlarge'
|
||||
}];
|
||||
return [
|
||||
'p-avatar p-component',
|
||||
{
|
||||
'p-avatar-image': this.image != null,
|
||||
'p-avatar-circle': this.shape === 'circle',
|
||||
'p-avatar-lg': this.size === 'large',
|
||||
'p-avatar-xl': this.size === 'xlarge'
|
||||
}
|
||||
];
|
||||
},
|
||||
iconClass() {
|
||||
return ['p-avatar-icon', this.icon];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
export interface AvatarGroupProps {
|
||||
}
|
||||
export interface AvatarGroupProps {}
|
||||
|
||||
export interface AvatarGroupSlots {
|
||||
}
|
||||
export interface AvatarGroupSlots {}
|
||||
|
||||
export declare type AvatarGroupEmits = {
|
||||
}
|
||||
export declare type AvatarGroupEmits = {};
|
||||
|
||||
declare class AvatarGroup extends ClassComponent<AvatarGroupProps, AvatarGroupSlots, AvatarGroupEmits> { }
|
||||
declare class AvatarGroup extends ClassComponent<AvatarGroupProps, AvatarGroupSlots, AvatarGroupEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
AvatarGroup: GlobalComponentConstructor<AvatarGroup>
|
||||
AvatarGroup: GlobalComponentConstructor<AvatarGroup>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +24,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [AvatarGroup](https://www.primefaces.org/primevue/showcase/#/avatar)
|
||||
* - [AvatarGroup](https://www.primefaces.org/primevue/avatar)
|
||||
*
|
||||
*/
|
||||
export default AvatarGroup;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'AvatarGroup'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -29,14 +29,13 @@ export interface BadgeSlots {
|
|||
default: () => VNode[];
|
||||
}
|
||||
|
||||
export declare type BadgeEmits = {
|
||||
}
|
||||
export declare type BadgeEmits = {};
|
||||
|
||||
declare class Badge extends ClassComponent<BadgeProps, BadgeSlots, BadgeEmits> { }
|
||||
declare class Badge extends ClassComponent<BadgeProps, BadgeSlots, BadgeEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Badge: GlobalComponentConstructor<Badge>
|
||||
Badge: GlobalComponentConstructor<Badge>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +45,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Badge](https://www.primefaces.org/primevue/showcase/#/badge)
|
||||
* - [Badge](https://www.primefaces.org/primevue/badge)
|
||||
*
|
||||
*/
|
||||
export default Badge;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<span :class="badgeClass">
|
||||
<slot>{{value}}</slot>
|
||||
<slot>{{ value }}</slot>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -14,20 +14,23 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return this.$slots.default ? 'p-overlay-badge': this.badgeClass;
|
||||
return this.$slots.default ? 'p-overlay-badge' : this.badgeClass;
|
||||
},
|
||||
badgeClass() {
|
||||
return ['p-badge p-component', {
|
||||
'p-badge-no-gutter': this.value && String(this.value).length === 1,
|
||||
'p-badge-dot': !this.value && !this.$slots.default,
|
||||
'p-badge-lg': this.size === 'large',
|
||||
'p-badge-xl': this.size === 'xlarge',
|
||||
'p-badge-info': this.severity === 'info',
|
||||
'p-badge-success': this.severity === 'success',
|
||||
'p-badge-warning': this.severity === 'warning',
|
||||
'p-badge-danger': this.severity === 'danger'
|
||||
}];
|
||||
return [
|
||||
'p-badge p-component',
|
||||
{
|
||||
'p-badge-no-gutter': this.value && String(this.value).length === 1,
|
||||
'p-badge-dot': !this.value && !this.$slots.default,
|
||||
'p-badge-lg': this.size === 'large',
|
||||
'p-badge-xl': this.size === 'xlarge',
|
||||
'p-badge-info': this.severity === 'info',
|
||||
'p-badge-success': this.severity === 'success',
|
||||
'p-badge-warning': this.severity === 'warning',
|
||||
'p-badge-danger': this.severity === 'danger'
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import {DomHandler} from 'primevue/utils';
|
||||
import {UniqueComponentId} from 'primevue/utils';
|
||||
import { DomHandler } from 'primevue/utils';
|
||||
import { UniqueComponentId } from 'primevue/utils';
|
||||
|
||||
const BadgeDirective = {
|
||||
beforeMount(el, options) {
|
||||
const id = UniqueComponentId() + '_badge';
|
||||
|
||||
el.$_pbadgeId = id;
|
||||
|
||||
let badge = document.createElement('span');
|
||||
|
||||
badge.id = id;
|
||||
badge.className = 'p-badge p-component';
|
||||
|
||||
|
@ -20,8 +22,7 @@ const BadgeDirective = {
|
|||
if (String(options.value).length === 1) {
|
||||
DomHandler.addClass(badge, 'p-badge-no-gutter');
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DomHandler.addClass(badge, 'p-badge-dot');
|
||||
}
|
||||
|
||||
|
@ -39,12 +40,9 @@ const BadgeDirective = {
|
|||
DomHandler.removeClass(badge, 'p-badge-dot');
|
||||
}
|
||||
|
||||
if (String(options.value).length === 1)
|
||||
DomHandler.addClass(badge, 'p-badge-no-gutter');
|
||||
else
|
||||
DomHandler.removeClass(badge, 'p-badge-no-gutter');
|
||||
}
|
||||
else if (!options.value && !DomHandler.hasClass(badge, 'p-badge-dot')) {
|
||||
if (String(options.value).length === 1) DomHandler.addClass(badge, 'p-badge-no-gutter');
|
||||
else DomHandler.removeClass(badge, 'p-badge-no-gutter');
|
||||
} else if (!options.value && !DomHandler.hasClass(badge, 'p-badge-dot')) {
|
||||
DomHandler.addClass(badge, 'p-badge-dot');
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ describe('directive badge should exist', () => {
|
|||
const wrapper = mount({
|
||||
template: '<i class="pi pi-bell mr-4 p-text-secondary" style="font-size: 2rem" v-badge="2"></i>',
|
||||
directives: {
|
||||
'badge': BadgeDirective
|
||||
badge: BadgeDirective
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -33,18 +33,18 @@ export declare type BlockUIEmits = {
|
|||
/**
|
||||
* Fired when the element gets blocked.
|
||||
*/
|
||||
'block': () => void;
|
||||
block: () => void;
|
||||
/**
|
||||
* Fired when the element gets unblocked.
|
||||
*/
|
||||
'unblock': () => void;
|
||||
}
|
||||
unblock: () => void;
|
||||
};
|
||||
|
||||
declare class BlockUI extends ClassComponent<BlockUIProps, BlockUISlots, BlockUIEmits> { }
|
||||
declare class BlockUI extends ClassComponent<BlockUIProps, BlockUISlots, BlockUIEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
BlockUI: GlobalComponentConstructor<BlockUI>
|
||||
BlockUI: GlobalComponentConstructor<BlockUI>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [BlockUI](https://www.primefaces.org/primevue/showcase/#/blockui)
|
||||
* - [BlockUI](https://www.primefaces.org/primevue/blockui)
|
||||
*
|
||||
*/
|
||||
export default BlockUI;
|
||||
|
|
|
@ -11,7 +11,7 @@ config.global.mocks = {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
describe('BlockUI.vue', () => {
|
||||
it('should blocked and unblocked the panel', async () => {
|
||||
|
@ -34,7 +34,7 @@ describe('BlockUI.vue', () => {
|
|||
data() {
|
||||
return {
|
||||
blockedPanel: false
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
blockPanel() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler,ZIndexUtils} from 'primevue/utils';
|
||||
import { DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'BlockUI',
|
||||
|
@ -29,22 +29,21 @@ export default {
|
|||
}
|
||||
},
|
||||
mask: null,
|
||||
watch: {
|
||||
blocked(newValue) {
|
||||
if (newValue === true) this.block();
|
||||
else this.unblock();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.blocked) {
|
||||
this.block();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
blocked(newValue) {
|
||||
if (newValue === true)
|
||||
this.block();
|
||||
else
|
||||
this.unblock();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
block() {
|
||||
let styleClass = 'p-blockui p-component-overlay p-component-overlay-enter';
|
||||
|
||||
if (this.fullScreen) {
|
||||
styleClass += ' p-blockui-document';
|
||||
this.mask = document.createElement('div');
|
||||
|
@ -52,8 +51,7 @@ export default {
|
|||
document.body.appendChild(this.mask);
|
||||
DomHandler.addClass(document.body, 'p-overflow-hidden');
|
||||
document.activeElement.blur();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.mask = document.createElement('div');
|
||||
this.mask.setAttribute('class', styleClass);
|
||||
this.$refs.container.appendChild(this.mask);
|
||||
|
@ -73,18 +71,18 @@ export default {
|
|||
},
|
||||
removeMask() {
|
||||
ZIndexUtils.clear(this.mask);
|
||||
if (this.fullScreen) {
|
||||
|
||||
if (this.fullScreen) {
|
||||
document.body.removeChild(this.mask);
|
||||
DomHandler.removeClass(document.body, 'p-overflow-hidden');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.$refs.container.removeChild(this.mask);
|
||||
}
|
||||
|
||||
this.$emit('unblock');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -31,14 +31,13 @@ export interface BreadcrumbSlots {
|
|||
}) => VNode[];
|
||||
}
|
||||
|
||||
export declare type BreadcrumbEmits = {
|
||||
}
|
||||
export declare type BreadcrumbEmits = {};
|
||||
|
||||
declare class Breadcrumb extends ClassComponent<BreadcrumbProps, BreadcrumbSlots, BreadcrumbEmits> { }
|
||||
declare class Breadcrumb extends ClassComponent<BreadcrumbProps, BreadcrumbSlots, BreadcrumbEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Breadcrumb: GlobalComponentConstructor<Breadcrumb>
|
||||
Breadcrumb: GlobalComponentConstructor<Breadcrumb>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,11 +47,11 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Helper API:
|
||||
*
|
||||
* - [MenuItem](https://www.primefaces.org/primevue/showcase/#/menumodel)
|
||||
* - [MenuItem](https://www.primefaces.org/primevue/menumodel)
|
||||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Breadcrumb](https://www.primefaces.org/primevue/showcase/#/breadcrumb)
|
||||
* - [Breadcrumb](https://www.primefaces.org/primevue/breadcrumb)
|
||||
*
|
||||
*/
|
||||
export default Breadcrumb;
|
||||
|
|
|
@ -8,14 +8,8 @@ describe('Breadcrumb', () => {
|
|||
stubs: ['router-link']
|
||||
},
|
||||
props: {
|
||||
home: {icon: 'pi pi-home', to: '/'},
|
||||
model: [
|
||||
{label: 'Computer'},
|
||||
{label: 'Notebook'},
|
||||
{label: 'Accessories'},
|
||||
{label: 'Backpacks'},
|
||||
{label: 'Item'}
|
||||
]
|
||||
home: { icon: 'pi pi-home', to: '/' },
|
||||
model: [{ label: 'Computer' }, { label: 'Notebook' }, { label: 'Accessories' }, { label: 'Backpacks' }, { label: 'Item' }]
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
'BreadcrumbItem': BreadcrumbItem
|
||||
BreadcrumbItem: BreadcrumbItem
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<li :class="containerClass(item)" v-if="visible()">
|
||||
<li v-if="visible()" :class="containerClass(item)">
|
||||
<template v-if="!template">
|
||||
<router-link v-if="item.to" :to="item.to" custom v-slot="{navigate, href, isActive, isExactActive}">
|
||||
<a :href="href" :class="linkClass({isActive, isExactActive})" @click="onClick($event, navigate)">
|
||||
<router-link v-if="item.to" v-slot="{ navigate, href, isActive, isExactActive }" :to="item.to" custom>
|
||||
<a :href="href" :class="linkClass({ isActive, isExactActive })" @click="onClick($event, navigate)">
|
||||
<span v-if="item.icon" :class="iconClass"></span>
|
||||
<span v-if="item.label" class="p-menuitem-text">{{label()}}</span>
|
||||
<span v-if="item.label" class="p-menuitem-text">{{ label() }}</span>
|
||||
</a>
|
||||
</router-link>
|
||||
<a v-else :href="item.url||'#'" :class="linkClass()" @click="onClick" :target="item.target">
|
||||
<a v-else :href="item.url || '#'" :class="linkClass()" @click="onClick" :target="item.target">
|
||||
<span v-if="item.icon" :class="iconClass"></span>
|
||||
<span v-if="item.label" class="p-menuitem-text">{{label()}}</span>
|
||||
<span v-if="item.label" class="p-menuitem-text">{{ label() }}</span>
|
||||
</a>
|
||||
</template>
|
||||
<component v-else :is="template" :item="item"></component>
|
||||
|
@ -38,22 +38,25 @@ export default {
|
|||
}
|
||||
},
|
||||
containerClass(item) {
|
||||
return [{'p-disabled': this.disabled(item)}, this.item.class];
|
||||
return [{ 'p-disabled': this.disabled(item) }, this.item.class];
|
||||
},
|
||||
linkClass(routerProps) {
|
||||
return ['p-menuitem-link', {
|
||||
'router-link-active': routerProps && routerProps.isActive,
|
||||
'router-link-active-exact': this.exact && routerProps && routerProps.isExactActive
|
||||
}];
|
||||
return [
|
||||
'p-menuitem-link',
|
||||
{
|
||||
'router-link-active': routerProps && routerProps.isActive,
|
||||
'router-link-active-exact': this.exact && routerProps && routerProps.isExactActive
|
||||
}
|
||||
];
|
||||
},
|
||||
visible() {
|
||||
return (typeof this.item.visible === 'function' ? this.item.visible() : this.item.visible !== false);
|
||||
return typeof this.item.visible === 'function' ? this.item.visible() : this.item.visible !== false;
|
||||
},
|
||||
disabled(item) {
|
||||
return (typeof item.disabled === 'function' ? item.disabled() : item.disabled);
|
||||
return typeof item.disabled === 'function' ? item.disabled() : item.disabled;
|
||||
},
|
||||
label() {
|
||||
return (typeof this.item.label === 'function' ? this.item.label() : this.item.label);
|
||||
return typeof this.item.label === 'function' ? this.item.label() : this.item.label;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -61,5 +64,5 @@ export default {
|
|||
return ['p-menuitem-icon', this.item.icon];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -9,8 +9,8 @@ export interface ButtonProps extends ButtonHTMLAttributes {
|
|||
*/
|
||||
style?: any;
|
||||
/**
|
||||
* Style class of the button.
|
||||
*/
|
||||
* Style class of the button.
|
||||
*/
|
||||
class?: any;
|
||||
/**
|
||||
* Text of the button.
|
||||
|
@ -25,6 +25,10 @@ export interface ButtonProps extends ButtonHTMLAttributes {
|
|||
* Default value is 'left'.
|
||||
*/
|
||||
iconPos?: ButtonIconPosType;
|
||||
/**
|
||||
* Style class of the icon.
|
||||
*/
|
||||
iconClass?: string | undefined;
|
||||
/**
|
||||
* Value of the badge.
|
||||
*/
|
||||
|
@ -51,14 +55,13 @@ export interface ButtonSlots {
|
|||
default: () => VNode[];
|
||||
}
|
||||
|
||||
export declare type ButtonEmits = {
|
||||
}
|
||||
export declare type ButtonEmits = {};
|
||||
|
||||
declare class Button extends ClassComponent<ButtonProps, ButtonSlots, ButtonEmits> { }
|
||||
declare class Button extends ClassComponent<ButtonProps, ButtonSlots, ButtonEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Button: GlobalComponentConstructor<Button>
|
||||
Button: GlobalComponentConstructor<Button>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +71,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Button](https://www.primefaces.org/primevue/showcase/#/button)
|
||||
* - [Button](https://www.primefaces.org/primevue/button)
|
||||
*
|
||||
*/
|
||||
export default Button;
|
||||
|
|
|
@ -3,16 +3,16 @@ import { mount } from '@vue/test-utils';
|
|||
import Button from '@/components/button/Button.vue';
|
||||
|
||||
describe('Button.vue', () => {
|
||||
it('is Button element exist', () => {
|
||||
const wrapper = mount(Button);
|
||||
it('is Button element exist', () => {
|
||||
const wrapper = mount(Button);
|
||||
|
||||
expect(wrapper.find('.p-button.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-button.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-button-label').exists()).toBe(true);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Button.vue', () => {
|
||||
it('is icon exist and right position', () => {
|
||||
it('is icon exist and right position', () => {
|
||||
const icon = 'pi pi-discord';
|
||||
const iconPos = 'right';
|
||||
const label = 'Save';
|
||||
|
@ -23,28 +23,27 @@ describe('Button.vue', () => {
|
|||
props
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-button-icon-only').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-button-icon-only').exists()).toBe(true);
|
||||
|
||||
wrapper = mount(Button, {
|
||||
props: { ...props, label }
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-button-icon.p-button-icon-' + iconPos).exists()).toBe(true);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Button.vue', () => {
|
||||
it('is badge working', () => {
|
||||
const badge = '5';
|
||||
const badgeClass= 'p-badge-danger';
|
||||
const badgeClass = 'p-badge-danger';
|
||||
const wrapper = mount(Button, {
|
||||
props: { badge, badgeClass }
|
||||
});
|
||||
|
||||
|
||||
expect(wrapper.find('.p-badge').text()).toEqual(badge);
|
||||
expect(wrapper.find('.' + badgeClass).exists()).toBe(true);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Button.vue', () => {
|
||||
|
@ -59,9 +58,9 @@ describe('Button.vue', () => {
|
|||
|
||||
expect(wrapper.find('.p-disabled').exists()).toBe(false);
|
||||
|
||||
await wrapper.setProps({ loading: true })
|
||||
await wrapper.setProps({ loading: true });
|
||||
const array = loadingIcon.split(' ');
|
||||
const lastIcon = '.' + array.join('.');
|
||||
const lastIcon = '.' + array.join('.');
|
||||
|
||||
expect(wrapper.find('.p-button-loading').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-button-loading-icon' + lastIcon).exists()).toBe(true);
|
||||
|
@ -69,17 +68,17 @@ describe('Button.vue', () => {
|
|||
await wrapper.setProps({ loading: false });
|
||||
|
||||
expect(wrapper.find('.p-button-loading').exists()).toBe(false);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Button.vue', () => {
|
||||
it('should render default slot', () => {
|
||||
const wrapper = mount(Button, {
|
||||
slots: {
|
||||
default: h('span', {class: 'ml-2 font-bold'}, 'Default PrimeVue Button')
|
||||
default: h('span', { class: 'ml-2 font-bold' }, 'Default PrimeVue Button')
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toBe('<button class="p-button p-component" type="button"><span class="ml-2 font-bold">Default PrimeVue Button</span></button>');
|
||||
})
|
||||
});
|
||||
});
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<button :class="buttonClass" type="button" :aria-label="defaultAriaLabel" v-ripple :disabled="disabled">
|
||||
<button v-ripple :class="buttonClass" type="button" :aria-label="defaultAriaLabel" :disabled="disabled">
|
||||
<slot>
|
||||
<span v-if="loading && !icon" :class="iconClass"></span>
|
||||
<span v-if="icon" :class="iconClass"></span>
|
||||
<span class="p-button-label">{{label||' '}}</span>
|
||||
<span v-if="badge" :class="badgeStyleClass">{{badge}}</span>
|
||||
<span v-if="loading && !icon" :class="iconStyleClass"></span>
|
||||
<span v-if="icon" :class="iconStyleClass"></span>
|
||||
<span class="p-button-label">{{ label || ' ' }}</span>
|
||||
<span v-if="badge" :class="badgeStyleClass">{{ badge }}</span>
|
||||
</slot>
|
||||
</button>
|
||||
</template>
|
||||
|
@ -25,6 +25,10 @@ export default {
|
|||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
iconClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
badge: {
|
||||
type: String
|
||||
},
|
||||
|
@ -50,35 +54,39 @@ export default {
|
|||
'p-disabled': this.$attrs.disabled || this.loading,
|
||||
'p-button-loading': this.loading,
|
||||
'p-button-loading-label-only': this.loading && !this.icon && this.label
|
||||
}
|
||||
};
|
||||
},
|
||||
iconClass() {
|
||||
iconStyleClass() {
|
||||
return [
|
||||
this.loading ? 'p-button-loading-icon ' + this.loadingIcon : this.icon,
|
||||
'p-button-icon',
|
||||
this.iconClass,
|
||||
{
|
||||
'p-button-icon-left': this.iconPos === 'left' && this.label,
|
||||
'p-button-icon-right': this.iconPos === 'right' && this.label,
|
||||
'p-button-icon-top': this.iconPos === 'top' && this.label,
|
||||
'p-button-icon-bottom': this.iconPos === 'bottom' && this.label
|
||||
}
|
||||
]
|
||||
];
|
||||
},
|
||||
badgeStyleClass() {
|
||||
return [
|
||||
'p-badge p-component', this.badgeClass, {
|
||||
'p-badge-no-gutter': this.badge && String(this.badge).length === 1
|
||||
}]
|
||||
'p-badge p-component',
|
||||
this.badgeClass,
|
||||
{
|
||||
'p-badge-no-gutter': this.badge && String(this.badge).length === 1
|
||||
}
|
||||
];
|
||||
},
|
||||
disabled() {
|
||||
return this.$attrs.disabled || this.loading;
|
||||
},
|
||||
defaultAriaLabel() {
|
||||
return (this.label ? this.label + (this.badge ? ' ' + this.badge : '') : this.$attrs['aria-label']);
|
||||
return this.label ? this.label + (this.badge ? ' ' + this.badge : '') : this.$attrs['aria-label'];
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
ripple: Ripple
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
|||
|
||||
type CalendarValueType = Date | Date[] | undefined;
|
||||
|
||||
type CalendarSlotDateType = { day: number; month: number; year: number; today: boolean; selectable: boolean }
|
||||
type CalendarSlotDateType = { day: number; month: number; year: number; today: boolean; selectable: boolean };
|
||||
|
||||
type CalendarSelectionModeType = 'single' | 'multiple' | 'range' | undefined;
|
||||
|
||||
|
@ -330,7 +330,7 @@ export declare type CalendarEmits = {
|
|||
* Callback to invoke when input field is being typed.
|
||||
* @param {Event} event - Browser event
|
||||
*/
|
||||
'input': (event: Event) => void;
|
||||
input: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke when a date is selected.
|
||||
* @param {Date} value - Selected value.
|
||||
|
@ -339,11 +339,11 @@ export declare type CalendarEmits = {
|
|||
/**
|
||||
* Callback to invoke when datepicker panel is shown.
|
||||
*/
|
||||
'show': () => void;
|
||||
show: () => void;
|
||||
/**
|
||||
* Callback to invoke when datepicker panel is hidden.
|
||||
*/
|
||||
'hide': () => void;
|
||||
hide: () => void;
|
||||
/**
|
||||
* Callback to invoke when today button is clicked.
|
||||
* @param {Date} date - Today as a date instance.
|
||||
|
@ -368,23 +368,23 @@ export declare type CalendarEmits = {
|
|||
* Callback to invoke on focus of input field.
|
||||
* @param {Event} event - Focus event
|
||||
*/
|
||||
'focus': (event: Event) => void;
|
||||
focus: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke on blur of input field.
|
||||
* @param {CalendarBlurEvent} event - Blur event
|
||||
*/
|
||||
'blur': (event: CalendarBlurEvent) => void;
|
||||
blur: (event: CalendarBlurEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when a key is pressed.
|
||||
*/
|
||||
'keydown': (event: Event) => void;
|
||||
}
|
||||
keydown: (event: Event) => void;
|
||||
};
|
||||
|
||||
declare class Calendar extends ClassComponent<CalendarProps, CalendarSlots, CalendarEmits> { }
|
||||
declare class Calendar extends ClassComponent<CalendarProps, CalendarSlots, CalendarEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Calendar: GlobalComponentConstructor<Calendar>
|
||||
Calendar: GlobalComponentConstructor<Calendar>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,7 +394,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Calendar](https://www.primefaces.org/primevue/showcase/#/calendar)
|
||||
* - [Calendar](https://www.primefaces.org/primevue/calendar)
|
||||
*
|
||||
*/
|
||||
export default Calendar;
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('Calendar.vue', () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
it('should exist', async() => {
|
||||
it('should exist', async () => {
|
||||
expect(wrapper.find('.p-calendar.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-inputtext').exists()).toBe(true);
|
||||
|
||||
|
@ -35,19 +35,20 @@ describe('Calendar.vue', () => {
|
|||
it('should select a date', async () => {
|
||||
await wrapper.setProps({ inline: true });
|
||||
|
||||
const event = {day: 8, month: 2, year: 2022, today: false, selectable: true};
|
||||
const event = { day: 8, month: 2, year: 2022, today: false, selectable: true };
|
||||
|
||||
const onDateSelect = jest.spyOn(wrapper.vm, 'onDateSelect');
|
||||
|
||||
await wrapper.vm.onDateSelect({currentTarget: {focus: () => {}}}, event);
|
||||
expect(onDateSelect).toHaveBeenCalled()
|
||||
await wrapper.vm.onDateSelect({ currentTarget: { focus: () => {} } }, event);
|
||||
expect(onDateSelect).toHaveBeenCalled();
|
||||
});
|
||||
it('should calculate the correct view date when in range mode', async () => {
|
||||
const dateOne = new Date();
|
||||
const dateTwo = new Date();
|
||||
dateTwo.setFullYear(dateOne.getFullYear(), dateOne.getMonth(), dateOne.getDate() + 1)
|
||||
await wrapper.setProps({ selectionMode: 'range', showTime: true, modelValue: [dateOne, dateTwo] });
|
||||
|
||||
expect(wrapper.vm.viewDate).toEqual(dateTwo)
|
||||
dateTwo.setFullYear(dateOne.getFullYear(), dateOne.getMonth(), dateOne.getDate() + 1);
|
||||
await wrapper.setProps({ selectionMode: 'range', showTime: true, modelValue: [dateOne, dateTwo] });
|
||||
|
||||
expect(wrapper.vm.viewDate).toEqual(dateTwo);
|
||||
});
|
||||
});
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,7 @@
|
|||
import { VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
export interface CardProps {
|
||||
}
|
||||
export interface CardProps {}
|
||||
|
||||
export interface CardSlots {
|
||||
/**
|
||||
|
@ -27,14 +26,13 @@ export interface CardSlots {
|
|||
footer: () => VNode[];
|
||||
}
|
||||
|
||||
export declare type CardEmits = {
|
||||
}
|
||||
export declare type CardEmits = {};
|
||||
|
||||
declare class Card extends ClassComponent<CardProps, CardSlots, CardEmits> { }
|
||||
declare class Card extends ClassComponent<CardProps, CardSlots, CardEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Card: GlobalComponentConstructor<Card>
|
||||
Card: GlobalComponentConstructor<Card>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +42,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Card](https://www.primefaces.org/primevue/showcase/#/card)
|
||||
* - [Card](https://www.primefaces.org/primevue/card)
|
||||
*
|
||||
*/
|
||||
export default Card;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div class="p-card p-component">
|
||||
<div class="p-card-header" v-if="$slots.header">
|
||||
<div v-if="$slots.header" class="p-card-header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<div class="p-card-body">
|
||||
<div class="p-card-title" v-if="$slots.title"><slot name="title"></slot></div>
|
||||
<div class="p-card-subtitle" v-if="$slots.subtitle"><slot name="subtitle"></slot></div>
|
||||
<div v-if="$slots.title" class="p-card-title"><slot name="title"></slot></div>
|
||||
<div v-if="$slots.subtitle" class="p-card-subtitle"><slot name="subtitle"></slot></div>
|
||||
<div class="p-card-content">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
<div class="p-card-footer" v-if="$slots.footer">
|
||||
<div v-if="$slots.footer" class="p-card-footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -19,7 +19,7 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'Card'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -27,54 +27,64 @@ export interface CarouselProps {
|
|||
* Index of the first item.
|
||||
* Default value is 0.
|
||||
*/
|
||||
page?: number | undefined;
|
||||
page?: number | undefined;
|
||||
/**
|
||||
* Number of items per page.
|
||||
* Default value is 1.
|
||||
*/
|
||||
numVisible?: number | undefined;
|
||||
numVisible?: number | undefined;
|
||||
/**
|
||||
* Number of items to scroll.
|
||||
* Default value is 1.
|
||||
*/
|
||||
numScroll?: number | undefined;
|
||||
numScroll?: number | undefined;
|
||||
/**
|
||||
* An array of options for responsive design.
|
||||
* @see CarouselResponsiveOptions
|
||||
*/
|
||||
responsiveOptions?: CarouselResponsiveOptions[] | undefined;
|
||||
responsiveOptions?: CarouselResponsiveOptions[] | undefined;
|
||||
/**
|
||||
* Specifies the layout of the component, valid values are 'horizontal' and 'vertical'.
|
||||
* @see CarouselOrientationType
|
||||
* Default value is 'horizontal'.
|
||||
*/
|
||||
orientation?: CarouselOrientationType;
|
||||
orientation?: CarouselOrientationType;
|
||||
/**
|
||||
* Height of the viewport in vertical layout.
|
||||
* Default value is '300px'.
|
||||
*/
|
||||
verticalViewPortHeight?: string | undefined;
|
||||
verticalViewPortHeight?: string | undefined;
|
||||
/**
|
||||
* Style class of the viewport container.
|
||||
*/
|
||||
containerClass?: any;
|
||||
containerClass?: any;
|
||||
/**
|
||||
* Style class of main content.
|
||||
*/
|
||||
contentClass?: any;
|
||||
contentClass?: any;
|
||||
/**
|
||||
* Style class of the indicator items.
|
||||
*/
|
||||
indicatorsContentClass?: any;
|
||||
indicatorsContentClass?: any;
|
||||
/**
|
||||
* Defines if scrolling would be infinite.
|
||||
*/
|
||||
circular?: boolean | undefined;
|
||||
circular?: boolean | undefined;
|
||||
/**
|
||||
* Time in milliseconds to scroll items automatically.
|
||||
* Default value is 0.
|
||||
*/
|
||||
autoplayInterval?: number | undefined;
|
||||
autoplayInterval?: number | undefined;
|
||||
/**
|
||||
* Whether to display navigation buttons in container.
|
||||
* Default value is true.
|
||||
*/
|
||||
showNavigators?: boolean | undefined;
|
||||
/**
|
||||
* Whether to display indicator container.
|
||||
* Default value is true.
|
||||
*/
|
||||
showIndicators?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface CarouselSlots {
|
||||
|
@ -92,13 +102,13 @@ export interface CarouselSlots {
|
|||
*/
|
||||
index: number;
|
||||
}) => VNode[];
|
||||
/**
|
||||
/**
|
||||
* Custom header template.
|
||||
*/
|
||||
header: () => VNode[];
|
||||
/**
|
||||
* Custom footer template.
|
||||
*/
|
||||
/**
|
||||
* Custom footer template.
|
||||
*/
|
||||
footer: () => VNode[];
|
||||
}
|
||||
|
||||
|
@ -108,13 +118,13 @@ export declare type CarouselEmits = {
|
|||
* @param {number} value - New page value.
|
||||
*/
|
||||
'update:page': (value: number) => void;
|
||||
}
|
||||
};
|
||||
|
||||
declare class Carousel extends ClassComponent<CarouselProps, CarouselSlots, CarouselEmits> { }
|
||||
declare class Carousel extends ClassComponent<CarouselProps, CarouselSlots, CarouselEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Carousel: GlobalComponentConstructor<Carousel>
|
||||
Carousel: GlobalComponentConstructor<Carousel>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +134,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Carousel](https://www.primefaces.org/primevue/showcase/#/carousel)
|
||||
* - [Carousel](https://www.primefaces.org/primevue/carousel)
|
||||
*
|
||||
*/
|
||||
export default Carousel;
|
||||
|
|
|
@ -7,52 +7,52 @@ describe('Carousel.vue', () => {
|
|||
props: {
|
||||
value: [
|
||||
{
|
||||
"id": "1000",
|
||||
"code": "vbb124btr",
|
||||
"name": "Game Controller",
|
||||
"description": "Product Description",
|
||||
"image": "game-controller.jpg",
|
||||
"price": 99,
|
||||
"category": "Electronics",
|
||||
"quantity": 2,
|
||||
"inventoryStatus": "LOWSTOCK",
|
||||
"rating": 4
|
||||
id: '1000',
|
||||
code: 'vbb124btr',
|
||||
name: 'Game Controller',
|
||||
description: 'Product Description',
|
||||
image: 'game-controller.jpg',
|
||||
price: 99,
|
||||
category: 'Electronics',
|
||||
quantity: 2,
|
||||
inventoryStatus: 'LOWSTOCK',
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"code": "nvklal433",
|
||||
"name": "Black Watch",
|
||||
"description": "Product Description",
|
||||
"image": "black-watch.jpg",
|
||||
"price": 72,
|
||||
"category": "Accessories",
|
||||
"quantity": 61,
|
||||
"inventoryStatus": "INSTOCK",
|
||||
"rating": 4
|
||||
id: '1001',
|
||||
code: 'nvklal433',
|
||||
name: 'Black Watch',
|
||||
description: 'Product Description',
|
||||
image: 'black-watch.jpg',
|
||||
price: 72,
|
||||
category: 'Accessories',
|
||||
quantity: 61,
|
||||
inventoryStatus: 'INSTOCK',
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
"id": "1002",
|
||||
"code": "zz21cz3c1",
|
||||
"name": "Blue Band",
|
||||
"description": "Product Description",
|
||||
"image": "blue-band.jpg",
|
||||
"price": 79,
|
||||
"category": "Fitness",
|
||||
"quantity": 2,
|
||||
"inventoryStatus": "LOWSTOCK",
|
||||
"rating": 3
|
||||
id: '1002',
|
||||
code: 'zz21cz3c1',
|
||||
name: 'Blue Band',
|
||||
description: 'Product Description',
|
||||
image: 'blue-band.jpg',
|
||||
price: 79,
|
||||
category: 'Fitness',
|
||||
quantity: 2,
|
||||
inventoryStatus: 'LOWSTOCK',
|
||||
rating: 3
|
||||
},
|
||||
{
|
||||
"id": "1003",
|
||||
"code": "244wgerg2",
|
||||
"name": "Blue T-Shirt",
|
||||
"description": "Product Description",
|
||||
"image": "blue-t-shirt.jpg",
|
||||
"price": 29,
|
||||
"category": "Clothing",
|
||||
"quantity": 25,
|
||||
"inventoryStatus": "INSTOCK",
|
||||
"rating": 5
|
||||
id: '1003',
|
||||
code: '244wgerg2',
|
||||
name: 'Blue T-Shirt',
|
||||
description: 'Product Description',
|
||||
image: 'blue-t-shirt.jpg',
|
||||
price: 29,
|
||||
category: 'Clothing',
|
||||
quantity: 25,
|
||||
inventoryStatus: 'INSTOCK',
|
||||
rating: 5
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -74,11 +74,13 @@ describe('Carousel.vue', () => {
|
|||
expect(wrapper.findAll('.p-carousel-item').length).toBe(4);
|
||||
|
||||
const firstItem = wrapper.findAll('.p-carousel-item')[0];
|
||||
|
||||
expect(firstItem.classes()).toContain('p-carousel-item-active');
|
||||
|
||||
const nextBtn = wrapper.find('.p-carousel-next');
|
||||
|
||||
await nextBtn.trigger('click');
|
||||
|
||||
expect(firstItem.classes()).not.toContain('p-carousel-item-active');
|
||||
})
|
||||
});
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,7 @@ export interface CascadeSelectChangeEvent {
|
|||
/**
|
||||
* @extends CascadeSelectChangeEvent
|
||||
*/
|
||||
export interface CascadeSelectGroupChangeEvent extends CascadeSelectChangeEvent { }
|
||||
export interface CascadeSelectGroupChangeEvent extends CascadeSelectChangeEvent {}
|
||||
|
||||
export interface CascadeSelectProps {
|
||||
/**
|
||||
|
@ -121,6 +121,11 @@ export interface CascadeSelectProps {
|
|||
* Default value is true.
|
||||
*/
|
||||
autoOptionFocus?: boolean | undefined;
|
||||
/**
|
||||
* When enabled, the focused option is selected/opened.
|
||||
* Default value is false.
|
||||
*/
|
||||
selectOnFocus?: boolean | undefined;
|
||||
/**
|
||||
* Locale to use in searching. The default locale is the host environment's current locale.
|
||||
*/
|
||||
|
@ -205,22 +210,22 @@ export declare type CascadeSelectEmits = {
|
|||
* Callback to invoke on value change.
|
||||
* @param { CascadeSelectChangeEvent } event - Custom change event.
|
||||
*/
|
||||
'change': (event: CascadeSelectChangeEvent) => void;
|
||||
change: (event: CascadeSelectChangeEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when the component receives focus.
|
||||
* @param {Event} event - Browser event.
|
||||
*/
|
||||
'focus': (event: Event) => void;
|
||||
focus: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke when the component loses focus.
|
||||
* @param {Event} event - Browser event.
|
||||
*/
|
||||
'blur': (event: Event) => void;
|
||||
blur: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke on click.
|
||||
* @param { Event } event - Browser event.
|
||||
*/
|
||||
'click': (event: Event) => void;
|
||||
click: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke when a group changes.
|
||||
* @param { CascadeSelectGroupChangeEvent } event - Custom change event.
|
||||
|
@ -237,18 +242,18 @@ export declare type CascadeSelectEmits = {
|
|||
/**
|
||||
* Callback to invoke when the overlay is shown.
|
||||
*/
|
||||
'show': () => void;
|
||||
show: () => void;
|
||||
/**
|
||||
* Callback to invoke when the overlay is hidden.
|
||||
*/
|
||||
'hide': () => void;
|
||||
}
|
||||
hide: () => void;
|
||||
};
|
||||
|
||||
declare class CascadeSelect extends ClassComponent<CascadeSelectProps, CascadeSelectSlots, CascadeSelectEmits> { }
|
||||
declare class CascadeSelect extends ClassComponent<CascadeSelectProps, CascadeSelectSlots, CascadeSelectEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
CascadeSelect: GlobalComponentConstructor<CascadeSelect>
|
||||
CascadeSelect: GlobalComponentConstructor<CascadeSelect>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +263,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [CascadeSelect](https://www.primefaces.org/primevue/showcase/#/cascadeselect)
|
||||
* - [CascadeSelect](https://www.primefaces.org/primevue/cascadeselect)
|
||||
*
|
||||
*/
|
||||
export default CascadeSelect;
|
||||
|
|
|
@ -23,19 +23,18 @@ describe('CascadeSelect.vue', () => {
|
|||
{
|
||||
name: 'New South Wales',
|
||||
cities: [
|
||||
{cname: 'Sydney', code: 'A-SY'},
|
||||
{cname: 'Newcastle', code: 'A-NE'},
|
||||
{cname: 'Wollongong', code: 'A-WO'}
|
||||
{ cname: 'Sydney', code: 'A-SY' },
|
||||
{ cname: 'Newcastle', code: 'A-NE' },
|
||||
{ cname: 'Wollongong', code: 'A-WO' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Queensland',
|
||||
cities: [
|
||||
{cname: 'Brisbane', code: 'A-BR'},
|
||||
{cname: 'Townsville', code: 'A-TO'}
|
||||
{ cname: 'Brisbane', code: 'A-BR' },
|
||||
{ cname: 'Townsville', code: 'A-TO' }
|
||||
]
|
||||
},
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -45,18 +44,17 @@ describe('CascadeSelect.vue', () => {
|
|||
{
|
||||
name: 'Quebec',
|
||||
cities: [
|
||||
{cname: 'Montreal', code: 'C-MO'},
|
||||
{cname: 'Quebec City', code: 'C-QU'}
|
||||
{ cname: 'Montreal', code: 'C-MO' },
|
||||
{ cname: 'Quebec City', code: 'C-QU' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Ontario',
|
||||
cities: [
|
||||
{cname: 'Ottawa', code: 'C-OT'},
|
||||
{cname: 'Toronto', code: 'C-TO'}
|
||||
{ cname: 'Ottawa', code: 'C-OT' },
|
||||
{ cname: 'Toronto', code: 'C-TO' }
|
||||
]
|
||||
},
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -66,26 +64,26 @@ describe('CascadeSelect.vue', () => {
|
|||
{
|
||||
name: 'California',
|
||||
cities: [
|
||||
{cname: 'Los Angeles', code: 'US-LA'},
|
||||
{cname: 'San Diego', code: 'US-SD'},
|
||||
{cname: 'San Francisco', code: 'US-SF'}
|
||||
{ cname: 'Los Angeles', code: 'US-LA' },
|
||||
{ cname: 'San Diego', code: 'US-SD' },
|
||||
{ cname: 'San Francisco', code: 'US-SF' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Florida',
|
||||
cities: [
|
||||
{cname: 'Jacksonville', code: 'US-JA'},
|
||||
{cname: 'Miami', code: 'US-MI'},
|
||||
{cname: 'Tampa', code: 'US-TA'},
|
||||
{cname: 'Orlando', code: 'US-OR'}
|
||||
{ cname: 'Jacksonville', code: 'US-JA' },
|
||||
{ cname: 'Miami', code: 'US-MI' },
|
||||
{ cname: 'Tampa', code: 'US-TA' },
|
||||
{ cname: 'Orlando', code: 'US-OR' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Texas',
|
||||
cities: [
|
||||
{cname: 'Austin', code: 'US-AU'},
|
||||
{cname: 'Dallas', code: 'US-DA'},
|
||||
{cname: 'Houston', code: 'US-HO'}
|
||||
{ cname: 'Austin', code: 'US-AU' },
|
||||
{ cname: 'Dallas', code: 'US-DA' },
|
||||
{ cname: 'Houston', code: 'US-HO' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -98,11 +96,11 @@ describe('CascadeSelect.vue', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should exist', async() => {
|
||||
it('should exist', async () => {
|
||||
expect(wrapper.find('.p-cascadeselect.p-component').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should show list and sublist', async() => {
|
||||
it('should show list and sublist', async () => {
|
||||
expect(wrapper.find('.p-cascadeselect.p-component').exists()).toBe(true);
|
||||
|
||||
await wrapper.trigger('click');
|
||||
|
@ -112,6 +110,7 @@ describe('CascadeSelect.vue', () => {
|
|||
expect(wrapper.findAll('.p-cascadeselect-item-text')[0].text()).toBe('Australia');
|
||||
|
||||
const firstGroup = wrapper.findAll('.p-cascadeselect-item-content')[0];
|
||||
|
||||
await firstGroup.trigger('click');
|
||||
|
||||
expect(wrapper.find('.p-cascadeselect-panel.p-cascadeselect-sublist').exists()).toBe(true);
|
||||
|
|
|
@ -1,13 +1,32 @@
|
|||
<template>
|
||||
<div ref="container" :class="containerClass" @click="onContainerClick($event)">
|
||||
<div class="p-hidden-accessible">
|
||||
<input ref="focusInput" :id="inputId" type="text" :style="inputStyle" :class="inputClass" readonly :disabled="disabled" :placeholder="placeholder" :tabindex="!disabled ? tabindex : -1"
|
||||
role="combobox" :aria-label="ariaLabel" :aria-labelledby="ariaLabelledby" aria-haspopup="tree" :aria-expanded="overlayVisible" :aria-controls="id + '_tree'" :aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@focus="onFocus" @blur="onBlur" @keydown="onKeyDown" v-bind="inputProps" />
|
||||
<input
|
||||
ref="focusInput"
|
||||
:id="inputId"
|
||||
type="text"
|
||||
:style="inputStyle"
|
||||
:class="inputClass"
|
||||
readonly
|
||||
:disabled="disabled"
|
||||
:placeholder="placeholder"
|
||||
:tabindex="!disabled ? tabindex : -1"
|
||||
role="combobox"
|
||||
:aria-label="ariaLabel"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
aria-haspopup="tree"
|
||||
:aria-expanded="overlayVisible"
|
||||
:aria-controls="id + '_tree'"
|
||||
:aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@keydown="onKeyDown"
|
||||
v-bind="inputProps"
|
||||
/>
|
||||
</div>
|
||||
<span :class="labelClass">
|
||||
<slot name="value" :value="modelValue" :placeholder="placeholder">
|
||||
{{label}}
|
||||
{{ label }}
|
||||
</slot>
|
||||
</span>
|
||||
<div class="p-cascadeselect-trigger" role="button" tabindex="-1" aria-hidden="true">
|
||||
|
@ -16,18 +35,32 @@
|
|||
</slot>
|
||||
</div>
|
||||
<span role="status" aria-live="polite" class="p-hidden-accessible">
|
||||
{{searchResultMessageText}}
|
||||
{{ searchResultMessageText }}
|
||||
</span>
|
||||
<Portal :appendTo="appendTo">
|
||||
<transition name="p-connected-overlay" @enter="onOverlayEnter" @after-enter="onOverlayAfterEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
|
||||
<div v-if="overlayVisible" :ref="overlayRef" :style="panelStyle" :class="panelStyleClass" @click="onOverlayClick" @keydown="onOverlayKeyDown" v-bind="panelProps">
|
||||
<div class="p-cascadeselect-items-wrapper">
|
||||
<CascadeSelectSub :id="id + '_tree'" role="tree" aria-orientation="horizontal" :selectId="id" :focusedOptionId="focused ? focusedOptionId : undefined"
|
||||
:options="processedOptions" :activeOptionPath="activeOptionPath" :level="0" :templates="$slots" :optionLabel="optionLabel" :optionValue="optionValue" :optionDisabled="optionDisabled"
|
||||
:optionGroupLabel="optionGroupLabel" :optionGroupChildren="optionGroupChildren" @option-change="onOptionChange" />
|
||||
<CascadeSelectSub
|
||||
:id="id + '_tree'"
|
||||
role="tree"
|
||||
aria-orientation="horizontal"
|
||||
:selectId="id"
|
||||
:focusedOptionId="focused ? focusedOptionId : undefined"
|
||||
:options="processedOptions"
|
||||
:activeOptionPath="activeOptionPath"
|
||||
:level="0"
|
||||
:templates="$slots"
|
||||
:optionLabel="optionLabel"
|
||||
:optionValue="optionValue"
|
||||
:optionDisabled="optionDisabled"
|
||||
:optionGroupLabel="optionGroupLabel"
|
||||
:optionGroupChildren="optionGroupChildren"
|
||||
@option-change="onOptionChange"
|
||||
/>
|
||||
|
||||
<span role="status" aria-live="polite" class="p-hidden-accessible">
|
||||
{{selectedMessageText}}
|
||||
{{ selectedMessageText }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -37,7 +70,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils,UniqueComponentId} from 'primevue/utils';
|
||||
import { ConnectedOverlayScrollHandler, ObjectUtils, DomHandler, ZIndexUtils, UniqueComponentId } from 'primevue/utils';
|
||||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import CascadeSelectSub from './CascadeSelectSub.vue';
|
||||
import Portal from 'primevue/portal';
|
||||
|
@ -54,15 +87,36 @@ export default {
|
|||
optionGroupLabel: null,
|
||||
optionGroupChildren: null,
|
||||
placeholder: String,
|
||||
disabled: Boolean,
|
||||
disabled: Boolean,
|
||||
dataKey: null,
|
||||
inputId: null,
|
||||
inputStyle: null,
|
||||
inputClass: null,
|
||||
inputProps: null,
|
||||
panelStyle: null,
|
||||
panelClass: null,
|
||||
panelProps: null,
|
||||
inputId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
inputProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
panelClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
panelStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
panelProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
appendTo: {
|
||||
type: String,
|
||||
default: 'body'
|
||||
|
@ -79,6 +133,10 @@ export default {
|
|||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selectOnFocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
searchLocale: {
|
||||
type: String,
|
||||
default: undefined
|
||||
|
@ -109,7 +167,7 @@ export default {
|
|||
},
|
||||
'aria-labelledby': {
|
||||
type: String,
|
||||
default: null
|
||||
default: null
|
||||
},
|
||||
'aria-label': {
|
||||
type: String,
|
||||
|
@ -122,17 +180,15 @@ export default {
|
|||
overlay: null,
|
||||
searchTimeout: null,
|
||||
searchValue: null,
|
||||
selectOnFocus: false,
|
||||
focusOnHover: false,
|
||||
data() {
|
||||
return {
|
||||
id: UniqueComponentId(),
|
||||
focused: false,
|
||||
focusedOptionInfo: { index: -1, level: 0, parentKey: '' },
|
||||
activeOptionPath: [],
|
||||
overlayVisible: false,
|
||||
dirty: false
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
options() {
|
||||
|
@ -140,7 +196,7 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
this.id = this.$attrs.id || this.id;
|
||||
this.autoUpdateModel();
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.unbindOutsideClickListener();
|
||||
|
@ -177,6 +233,7 @@ export default {
|
|||
},
|
||||
getProccessedOptionLabel(processedOption) {
|
||||
const grouped = this.isProccessedOptionGroup(processedOption);
|
||||
|
||||
return grouped ? this.getOptionGroupLabel(processedOption.option, processedOption.level) : this.getOptionLabel(processedOption.option);
|
||||
},
|
||||
isProccessedOptionGroup(processedOption) {
|
||||
|
@ -185,17 +242,17 @@ export default {
|
|||
show(isFocus) {
|
||||
this.$emit('before-show');
|
||||
this.overlayVisible = true;
|
||||
this.activeOptionPath = this.findOptionPathByValue(this.modelValue);
|
||||
this.activeOptionPath = this.hasSelectedOption ? this.findOptionPathByValue(this.modelValue) : this.activeOptionPath;
|
||||
|
||||
if (this.hasSelectedOption && ObjectUtils.isNotEmpty(this.activeOptionPath)) {
|
||||
const processedOption = this.activeOptionPath[this.activeOptionPath.length - 1];
|
||||
this.focusedOptionInfo = { index: (this.autoOptionFocus ? processedOption.index : -1), level: processedOption.level, parentKey: processedOption.parentKey };
|
||||
}
|
||||
else {
|
||||
this.focusedOptionInfo = { index: (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1), level: 0, parentKey: '' };
|
||||
|
||||
this.focusedOptionInfo = { index: this.autoOptionFocus ? processedOption.index : -1, level: processedOption.level, parentKey: processedOption.parentKey };
|
||||
} else {
|
||||
this.focusedOptionInfo = { index: this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1, level: 0, parentKey: '' };
|
||||
}
|
||||
|
||||
isFocus && this.$refs.focusInput.focus();
|
||||
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||
},
|
||||
hide(isFocus) {
|
||||
const _hide = () => {
|
||||
|
@ -204,10 +261,12 @@ export default {
|
|||
this.activeOptionPath = [];
|
||||
this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' };
|
||||
|
||||
isFocus && this.$refs.focusInput.focus();
|
||||
}
|
||||
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||
};
|
||||
|
||||
setTimeout(() => { _hide() }, 0); // For ScreenReaders
|
||||
setTimeout(() => {
|
||||
_hide();
|
||||
}, 0); // For ScreenReaders
|
||||
},
|
||||
onFocus(event) {
|
||||
this.focused = true;
|
||||
|
@ -222,9 +281,12 @@ export default {
|
|||
onKeyDown(event) {
|
||||
if (this.disabled || this.loading) {
|
||||
event.preventDefault();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const metaKey = event.metaKey || event.ctrlKey;
|
||||
|
||||
switch (event.code) {
|
||||
case 'ArrowDown':
|
||||
this.onArrowDownKey(event);
|
||||
|
@ -275,7 +337,7 @@ export default {
|
|||
break;
|
||||
|
||||
default:
|
||||
if (ObjectUtils.isPrintableCharacter(event.key)) {
|
||||
if (!metaKey && ObjectUtils.isPrintableCharacter(event.key)) {
|
||||
!this.overlayVisible && this.show();
|
||||
this.searchOptions(event, event.key);
|
||||
}
|
||||
|
@ -284,25 +346,29 @@ export default {
|
|||
}
|
||||
},
|
||||
onOptionChange(event) {
|
||||
const { originalEvent, processedOption, isFocus } = event;
|
||||
const { originalEvent, processedOption, isFocus, isHide } = event;
|
||||
|
||||
if (ObjectUtils.isEmpty(processedOption)) return;
|
||||
|
||||
const { index, level, parentKey, children } = processedOption;
|
||||
const grouped = ObjectUtils.isNotEmpty(children);
|
||||
|
||||
const activeOptionPath = this.activeOptionPath.filter(p => p.parentKey !== parentKey);
|
||||
const activeOptionPath = this.activeOptionPath.filter((p) => p.parentKey !== parentKey);
|
||||
|
||||
activeOptionPath.push(processedOption);
|
||||
|
||||
this.focusedOptionInfo = { index, level, parentKey };
|
||||
this.activeOptionPath = activeOptionPath;
|
||||
|
||||
grouped ? this.onOptionGroupSelect(originalEvent, processedOption) : this.onOptionSelect(originalEvent, processedOption);
|
||||
isFocus && this.$refs.focusInput.focus();
|
||||
grouped ? this.onOptionGroupSelect(originalEvent, processedOption) : this.onOptionSelect(originalEvent, processedOption, isHide);
|
||||
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||
},
|
||||
onOptionSelect(event, processedOption) {
|
||||
onOptionSelect(event, processedOption, isHide = true) {
|
||||
const value = this.getOptionValue(processedOption.option);
|
||||
|
||||
this.activeOptionPath.forEach(p => p.selected = true);
|
||||
this.activeOptionPath.forEach((p) => (p.selected = true));
|
||||
this.updateModel(event, value);
|
||||
this.hide(true);
|
||||
isHide && this.hide(true);
|
||||
},
|
||||
onOptionGroupSelect(event, processedOption) {
|
||||
this.dirty = true;
|
||||
|
@ -315,7 +381,7 @@ export default {
|
|||
|
||||
if (!this.overlay || !this.overlay.contains(event.target)) {
|
||||
this.overlayVisible ? this.hide() : this.show();
|
||||
this.$refs.focusInput.focus();
|
||||
DomHandler.focus(this.$refs.focusInput);
|
||||
}
|
||||
|
||||
this.$emit('click', event);
|
||||
|
@ -349,13 +415,13 @@ export default {
|
|||
if (this.focusedOptionInfo.index !== -1) {
|
||||
const processedOption = this.visibleOptions[this.focusedOptionInfo.index];
|
||||
const grouped = this.isProccessedOptionGroup(processedOption);
|
||||
|
||||
!grouped && this.onOptionChange({ originalEvent: event, processedOption });
|
||||
}
|
||||
|
||||
this.overlayVisible && this.hide();
|
||||
event.preventDefault();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const optionIndex = this.focusedOptionInfo.index !== -1 ? this.findPrevOptionIndex(this.focusedOptionInfo.index) : this.findLastFocusedOptionIndex();
|
||||
|
||||
this.changeFocusedOptionIndex(event, optionIndex);
|
||||
|
@ -367,12 +433,12 @@ export default {
|
|||
onArrowLeftKey(event) {
|
||||
if (this.overlayVisible) {
|
||||
const processedOption = this.visibleOptions[this.focusedOptionInfo.index];
|
||||
const parentOption = this.activeOptionPath.find(p => p.key === processedOption.parentKey);
|
||||
const parentOption = this.activeOptionPath.find((p) => p.key === processedOption.parentKey);
|
||||
const matched = this.focusedOptionInfo.parentKey === '' || (parentOption && parentOption.key === this.focusedOptionInfo.parentKey);
|
||||
const root = ObjectUtils.isEmpty(processedOption.parent);
|
||||
|
||||
if (matched) {
|
||||
this.activeOptionPath = this.activeOptionPath.filter(p => p.parentKey !== this.focusedOptionInfo.parentKey);
|
||||
this.activeOptionPath = this.activeOptionPath.filter((p) => p.parentKey !== this.focusedOptionInfo.parentKey);
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
|
@ -390,14 +456,13 @@ export default {
|
|||
const grouped = this.isProccessedOptionGroup(processedOption);
|
||||
|
||||
if (grouped) {
|
||||
const matched = this.activeOptionPath.some(p => processedOption.key === p.key);
|
||||
const matched = this.activeOptionPath.some((p) => processedOption.key === p.key);
|
||||
|
||||
if (matched) {
|
||||
this.focusedOptionInfo = { index: -1, parentKey: processedOption.key };
|
||||
this.searchValue = '';
|
||||
this.onArrowDownKey(event);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.onOptionChange({ originalEvent: event, processedOption });
|
||||
}
|
||||
}
|
||||
|
@ -420,8 +485,7 @@ export default {
|
|||
onEnterKey(event) {
|
||||
if (!this.overlayVisible) {
|
||||
this.onArrowDownKey(event);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (this.focusedOptionInfo.index !== -1) {
|
||||
const processedOption = this.visibleOptions[this.focusedOptionInfo.index];
|
||||
const grouped = this.isProccessedOptionGroup(processedOption);
|
||||
|
@ -477,8 +541,7 @@ export default {
|
|||
alignOverlay() {
|
||||
if (this.appendTo === 'self') {
|
||||
DomHandler.relativePosition(this.overlay, this.$el);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px';
|
||||
DomHandler.absolutePosition(this.overlay, this.$el);
|
||||
}
|
||||
|
@ -490,6 +553,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
|
@ -522,6 +586,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', this.resizeListener);
|
||||
}
|
||||
},
|
||||
|
@ -541,31 +606,35 @@ export default {
|
|||
return this.isValidOption(processedOption) && this.isSelected(processedOption);
|
||||
},
|
||||
isSelected(processedOption) {
|
||||
return this.activeOptionPath.some(p => p.key === processedOption.key);
|
||||
return this.activeOptionPath.some((p) => p.key === processedOption.key);
|
||||
},
|
||||
findFirstOptionIndex() {
|
||||
return this.visibleOptions.findIndex(processedOption => this.isValidOption(processedOption));
|
||||
return this.visibleOptions.findIndex((processedOption) => this.isValidOption(processedOption));
|
||||
},
|
||||
findLastOptionIndex() {
|
||||
return ObjectUtils.findLastIndex(this.visibleOptions, processedOption => this.isValidOption(processedOption));
|
||||
return ObjectUtils.findLastIndex(this.visibleOptions, (processedOption) => this.isValidOption(processedOption));
|
||||
},
|
||||
findNextOptionIndex(index) {
|
||||
const matchedOptionIndex = index < (this.visibleOptions.length - 1) ? this.visibleOptions.slice(index + 1).findIndex(processedOption => this.isValidOption(processedOption)) : -1;
|
||||
const matchedOptionIndex = index < this.visibleOptions.length - 1 ? this.visibleOptions.slice(index + 1).findIndex((processedOption) => this.isValidOption(processedOption)) : -1;
|
||||
|
||||
return matchedOptionIndex > -1 ? matchedOptionIndex + index + 1 : index;
|
||||
},
|
||||
findPrevOptionIndex(index) {
|
||||
const matchedOptionIndex = index > 0 ? ObjectUtils.findLastIndex(this.visibleOptions.slice(0, index), processedOption => this.isValidOption(processedOption)) : -1;
|
||||
const matchedOptionIndex = index > 0 ? ObjectUtils.findLastIndex(this.visibleOptions.slice(0, index), (processedOption) => this.isValidOption(processedOption)) : -1;
|
||||
|
||||
return matchedOptionIndex > -1 ? matchedOptionIndex : index;
|
||||
},
|
||||
findSelectedOptionIndex() {
|
||||
return this.visibleOptions.findIndex(processedOption => this.isValidSelectedOption(processedOption));
|
||||
return this.visibleOptions.findIndex((processedOption) => this.isValidSelectedOption(processedOption));
|
||||
},
|
||||
findFirstFocusedOptionIndex() {
|
||||
const selectedIndex = this.findSelectedOptionIndex();
|
||||
|
||||
return selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex;
|
||||
},
|
||||
findLastFocusedOptionIndex() {
|
||||
const selectedIndex = this.findSelectedOptionIndex();
|
||||
|
||||
return selectedIndex < 0 ? this.findLastOptionIndex() : selectedIndex;
|
||||
},
|
||||
findOptionPathByValue(value, processedOptions, level = 0) {
|
||||
|
@ -582,6 +651,7 @@ export default {
|
|||
}
|
||||
|
||||
const matchedOptions = this.findOptionPathByValue(value, processedOption.children, level + 1);
|
||||
|
||||
if (matchedOptions) {
|
||||
matchedOptions.unshift(processedOption);
|
||||
|
||||
|
@ -596,11 +666,10 @@ export default {
|
|||
let matched = false;
|
||||
|
||||
if (this.focusedOptionInfo.index !== -1) {
|
||||
optionIndex = this.visibleOptions.slice(this.focusedOptionInfo.index).findIndex(processedOption => this.isOptionMatched(processedOption));
|
||||
optionIndex = optionIndex === -1 ? this.visibleOptions.slice(0, this.focusedOptionInfo.index).findIndex(processedOption => this.isOptionMatched(processedOption)) : optionIndex + this.focusedOptionInfo.index;
|
||||
}
|
||||
else {
|
||||
optionIndex = this.visibleOptions.findIndex(processedOption => this.isOptionMatched(processedOption));
|
||||
optionIndex = this.visibleOptions.slice(this.focusedOptionInfo.index).findIndex((processedOption) => this.isOptionMatched(processedOption));
|
||||
optionIndex = optionIndex === -1 ? this.visibleOptions.slice(0, this.focusedOptionInfo.index).findIndex((processedOption) => this.isOptionMatched(processedOption)) : optionIndex + this.focusedOptionInfo.index;
|
||||
} else {
|
||||
optionIndex = this.visibleOptions.findIndex((processedOption) => this.isOptionMatched(processedOption));
|
||||
}
|
||||
|
||||
if (optionIndex !== -1) {
|
||||
|
@ -632,13 +701,14 @@ export default {
|
|||
this.scrollInView();
|
||||
|
||||
if (this.selectOnFocus) {
|
||||
this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
|
||||
this.onOptionChange({ originalEvent: event, processedOption: this.visibleOptions[index], isHide: false });
|
||||
}
|
||||
}
|
||||
},
|
||||
scrollInView(index = -1) {
|
||||
const id = index !== -1 ? `${this.id}_${index}` : this.focusedOptionId;
|
||||
const element = DomHandler.findSingle(this.list, `li[id="${id}"]`);
|
||||
|
||||
if (element) {
|
||||
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
|
||||
}
|
||||
|
@ -646,8 +716,9 @@ export default {
|
|||
autoUpdateModel() {
|
||||
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
|
||||
this.focusedOptionInfo.index = this.findFirstFocusedOptionIndex();
|
||||
const value = this.getOptionValue(this.visibleOptions[this.focusedOptionInfo.index]);
|
||||
this.updateModel(null, value);
|
||||
this.onOptionChange({ processedOption: this.visibleOptions[this.focusedOptionInfo.index], isHide: false });
|
||||
|
||||
!this.overlayVisible && (this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' });
|
||||
}
|
||||
},
|
||||
updateModel(event, value) {
|
||||
|
@ -657,20 +728,21 @@ export default {
|
|||
createProcessedOptions(options, level = 0, parent = {}, parentKey = '') {
|
||||
const processedOptions = [];
|
||||
|
||||
options && options.forEach((option, index) => {
|
||||
const key = (parentKey !== '' ? parentKey + '_' : '') + index;
|
||||
const newOption = {
|
||||
option,
|
||||
index,
|
||||
level,
|
||||
key,
|
||||
parent,
|
||||
parentKey
|
||||
}
|
||||
options &&
|
||||
options.forEach((option, index) => {
|
||||
const key = (parentKey !== '' ? parentKey + '_' : '') + index;
|
||||
const newOption = {
|
||||
option,
|
||||
index,
|
||||
level,
|
||||
key,
|
||||
parent,
|
||||
parentKey
|
||||
};
|
||||
|
||||
newOption['children'] = this.createProcessedOptions(this.getOptionGroupChildren(option, level), level + 1, newOption, key);
|
||||
processedOptions.push(newOption);
|
||||
});
|
||||
newOption['children'] = this.createProcessedOptions(this.getOptionGroupChildren(option, level), level + 1, newOption, key);
|
||||
processedOptions.push(newOption);
|
||||
});
|
||||
|
||||
return processedOptions;
|
||||
},
|
||||
|
@ -680,25 +752,35 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-cascadeselect p-component p-inputwrapper', {
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused,
|
||||
'p-inputwrapper-filled': this.modelValue,
|
||||
'p-inputwrapper-focus': this.focused || this.overlayVisible,
|
||||
'p-overlay-open': this.overlayVisible
|
||||
}];
|
||||
return [
|
||||
'p-cascadeselect p-component p-inputwrapper',
|
||||
{
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused,
|
||||
'p-inputwrapper-filled': this.modelValue,
|
||||
'p-inputwrapper-focus': this.focused || this.overlayVisible,
|
||||
'p-overlay-open': this.overlayVisible
|
||||
}
|
||||
];
|
||||
},
|
||||
labelClass() {
|
||||
return ['p-cascadeselect-label', {
|
||||
'p-placeholder': this.label === this.placeholder,
|
||||
'p-cascadeselect-label-empty': !this.$slots['value'] && (this.label === 'p-emptylabel' || this.label.length === 0)
|
||||
}];
|
||||
return [
|
||||
'p-cascadeselect-label',
|
||||
{
|
||||
'p-placeholder': this.label === this.placeholder,
|
||||
'p-cascadeselect-label-empty': !this.$slots['value'] && (this.label === 'p-emptylabel' || this.label.length === 0)
|
||||
}
|
||||
];
|
||||
},
|
||||
panelStyleClass() {
|
||||
return ['p-cascadeselect-panel p-component', this.panelClass, {
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}];
|
||||
return [
|
||||
'p-cascadeselect-panel p-component',
|
||||
this.panelClass,
|
||||
{
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
},
|
||||
dropdownIconClass() {
|
||||
return ['p-cascadeselect-trigger-icon', this.loading ? this.loadingIcon : 'pi pi-chevron-down'];
|
||||
|
@ -711,7 +793,7 @@ export default {
|
|||
|
||||
if (this.hasSelectedOption) {
|
||||
const activeOptionPath = this.findOptionPathByValue(this.modelValue);
|
||||
const processedOption = activeOptionPath.length ? activeOptionPath[activeOptionPath.length - 1] : null;
|
||||
const processedOption = ObjectUtils.isNotEmpty(activeOptionPath) ? activeOptionPath[activeOptionPath.length - 1] : null;
|
||||
|
||||
return processedOption ? this.getOptionLabel(processedOption.option) : label;
|
||||
}
|
||||
|
@ -722,7 +804,8 @@ export default {
|
|||
return this.createProcessedOptions(this.options || []);
|
||||
},
|
||||
visibleOptions() {
|
||||
const processedOption = this.activeOptionPath.find(p => p.key === this.focusedOptionInfo.parentKey);
|
||||
const processedOption = this.activeOptionPath.find((p) => p.key === this.focusedOptionInfo.parentKey);
|
||||
|
||||
return processedOption ? processedOption.children : this.processedOptions;
|
||||
},
|
||||
equalityKey() {
|
||||
|
@ -749,15 +832,18 @@ export default {
|
|||
selectedMessageText() {
|
||||
return this.hasSelectedOption ? this.selectionMessageText.replaceAll('{0}', '1') : this.emptySelectionMessageText;
|
||||
},
|
||||
id() {
|
||||
return this.$attrs.id || UniqueComponentId();
|
||||
},
|
||||
focusedOptionId() {
|
||||
return this.focusedOptionInfo.index !== -1 ? `${this.id}${ObjectUtils.isNotEmpty(this.focusedOptionInfo.parentKey) ? '_' + this.focusedOptionInfo.parentKey : ''}_${this.focusedOptionInfo.index}` : null;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'CascadeSelectSub': CascadeSelectSub,
|
||||
'Portal': Portal
|
||||
CascadeSelectSub: CascadeSelectSub,
|
||||
Portal: Portal
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,24 +1,54 @@
|
|||
<template>
|
||||
<ul class="p-cascadeselect-panel p-cascadeselect-items">
|
||||
<template v-for="(processedOption,index) of options" :key="getOptionLabelToRender(processedOption)">
|
||||
<li :id="getOptionId(processedOption)" :class="['p-cascadeselect-item', {'p-cascadeselect-item-group': isOptionGroup(processedOption), 'p-cascadeselect-item-active p-highlight': isOptionActive(processedOption), 'p-focus': isOptionFocused(processedOption), 'p-disabled': isOptionDisabled(processedOption)}]"
|
||||
role="treeitem" :aria-label="getOptionLabelToRender(processedOption)" :aria-selected="isOptionGroup(processedOption) ? undefined : isOptionSelected(processedOption)" :aria-expanded="isOptionGroup(processedOption) ? isOptionActive(processedOption) : undefined"
|
||||
:aria-setsize="processedOption.length" :aria-posinset="index + 1" :aria-level="level + 1">
|
||||
<div class="p-cascadeselect-item-content" @click="onOptionClick($event, processedOption)" v-ripple>
|
||||
<template v-for="(processedOption, index) of options" :key="getOptionLabelToRender(processedOption)">
|
||||
<li
|
||||
:id="getOptionId(processedOption)"
|
||||
:class="[
|
||||
'p-cascadeselect-item',
|
||||
{
|
||||
'p-cascadeselect-item-group': isOptionGroup(processedOption),
|
||||
'p-cascadeselect-item-active p-highlight': isOptionActive(processedOption),
|
||||
'p-focus': isOptionFocused(processedOption),
|
||||
'p-disabled': isOptionDisabled(processedOption)
|
||||
}
|
||||
]"
|
||||
role="treeitem"
|
||||
:aria-label="getOptionLabelToRender(processedOption)"
|
||||
:aria-selected="isOptionGroup(processedOption) ? undefined : isOptionSelected(processedOption)"
|
||||
:aria-expanded="isOptionGroup(processedOption) ? isOptionActive(processedOption) : undefined"
|
||||
:aria-setsize="processedOption.length"
|
||||
:aria-posinset="index + 1"
|
||||
:aria-level="level + 1"
|
||||
>
|
||||
<div v-ripple class="p-cascadeselect-item-content" @click="onOptionClick($event, processedOption)">
|
||||
<component v-if="templates['option']" :is="templates['option']" :option="processedOption.option" />
|
||||
<span v-else class="p-cascadeselect-item-text">{{getOptionLabelToRender(processedOption)}}</span>
|
||||
<span v-else class="p-cascadeselect-item-text">{{ getOptionLabelToRender(processedOption) }}</span>
|
||||
<span v-if="isOptionGroup(processedOption)" class="p-cascadeselect-group-icon pi pi-angle-right" aria-hidden="true"></span>
|
||||
</div>
|
||||
<CascadeSelectSub v-if="isOptionGroup(processedOption) && isOptionActive(processedOption)" role="group" class="p-cascadeselect-sublist" :selectId="selectId" :focusedOptionId="focusedOptionId"
|
||||
:options="getOptionGroupChildren(processedOption)" :activeOptionPath="activeOptionPath" :level="level + 1" :templates="templates" :optionLabel="optionLabel" :optionValue="optionValue" :optionDisabled="optionDisabled"
|
||||
:optionGroupLabel="optionGroupLabel" :optionGroupChildren="optionGroupChildren" @option-change="onOptionChange" />
|
||||
<CascadeSelectSub
|
||||
v-if="isOptionGroup(processedOption) && isOptionActive(processedOption)"
|
||||
role="group"
|
||||
class="p-cascadeselect-sublist"
|
||||
:selectId="selectId"
|
||||
:focusedOptionId="focusedOptionId"
|
||||
:options="getOptionGroupChildren(processedOption)"
|
||||
:activeOptionPath="activeOptionPath"
|
||||
:level="level + 1"
|
||||
:templates="templates"
|
||||
:optionLabel="optionLabel"
|
||||
:optionValue="optionValue"
|
||||
:optionDisabled="optionDisabled"
|
||||
:optionGroupLabel="optionGroupLabel"
|
||||
:optionGroupChildren="optionGroupChildren"
|
||||
@option-change="onOptionChange"
|
||||
/>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ObjectUtils,DomHandler} from 'primevue/utils';
|
||||
import { ObjectUtils, DomHandler } from 'primevue/utils';
|
||||
import Ripple from 'primevue/ripple';
|
||||
|
||||
export default {
|
||||
|
@ -68,7 +98,7 @@ export default {
|
|||
return !this.isOptionGroup(processedOption) && this.isOptionActive(processedOption);
|
||||
},
|
||||
isOptionActive(processedOption) {
|
||||
return this.activeOptionPath.some(path => path.key === processedOption.key);
|
||||
return this.activeOptionPath.some((path) => path.key === processedOption.key);
|
||||
},
|
||||
isOptionFocused(processedOption) {
|
||||
return this.focusedOptionId === this.getOptionId(processedOption);
|
||||
|
@ -89,13 +119,13 @@ export default {
|
|||
const sublistWidth = this.$el.offsetParent ? this.$el.offsetWidth : DomHandler.getHiddenElementOuterWidth(this.$el);
|
||||
const itemOuterWidth = DomHandler.getOuterWidth(parentItem.children[0]);
|
||||
|
||||
if ((parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth) > (viewport.width - DomHandler.calculateScrollbarWidth())) {
|
||||
if (parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth > viewport.width - DomHandler.calculateScrollbarWidth()) {
|
||||
this.$el.style.left = '-100%';
|
||||
}
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
ripple: Ripple
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -44,21 +44,20 @@ export interface ChartProps {
|
|||
height?: number | undefined;
|
||||
}
|
||||
|
||||
export interface ChartSlots {
|
||||
}
|
||||
export interface ChartSlots {}
|
||||
|
||||
export declare type ChartEmits = {
|
||||
/**
|
||||
* Callback to invoke when a tab gets expanded.
|
||||
* @param {ChartSelectEvent} event - Custom select event.
|
||||
*/
|
||||
'select': (event: ChartSelectEvent) => void;
|
||||
select: (event: ChartSelectEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when chart is loaded.
|
||||
* @param {*} chart - Chart instance.
|
||||
*/
|
||||
'loaded': (chart: any) => void;
|
||||
}
|
||||
loaded: (chart: any) => void;
|
||||
};
|
||||
|
||||
declare class Chart extends ClassComponent<ChartProps, ChartSlots, ChartEmits> {
|
||||
/**
|
||||
|
@ -89,7 +88,7 @@ declare class Chart extends ClassComponent<ChartProps, ChartSlots, ChartEmits> {
|
|||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Chart: GlobalComponentConstructor<Chart>
|
||||
Chart: GlobalComponentConstructor<Chart>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +102,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Chart](https://www.primefaces.org/primevue/showcase/#/chart)
|
||||
* - [Chart](https://www.primefaces.org/primevue/chart)
|
||||
*
|
||||
*/
|
||||
export default Chart;
|
||||
|
|
|
@ -20,18 +20,9 @@ export default {
|
|||
height: {
|
||||
type: Number,
|
||||
default: 150
|
||||
},
|
||||
},
|
||||
chart: null,
|
||||
mounted() {
|
||||
this.initChart();
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
this.chart = null;
|
||||
}
|
||||
},
|
||||
chart: null,
|
||||
watch: {
|
||||
/*
|
||||
* Use deep watch to enable triggering watch for changes within structure
|
||||
|
@ -50,6 +41,15 @@ export default {
|
|||
this.reinit();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart();
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
this.chart = null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
import('chart.js/auto').then((module) => {
|
||||
|
@ -93,7 +93,7 @@ export default {
|
|||
const dataset = this.chart.getElementsAtEventForMode(event, 'dataset', { intersect: true }, false);
|
||||
|
||||
if (element && element[0] && dataset) {
|
||||
this.$emit('select', {originalEvent: event, element: element[0], dataset: dataset});
|
||||
this.$emit('select', { originalEvent: event, element: element[0], dataset: dataset });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -103,7 +103,7 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -51,8 +51,8 @@ export interface CheckboxProps {
|
|||
*/
|
||||
inputClass?: any | undefined;
|
||||
/**
|
||||
* Inline style of the input field.
|
||||
*/
|
||||
* Inline style of the input field.
|
||||
*/
|
||||
inputStyle?: any | undefined;
|
||||
/**
|
||||
* Uses to pass all properties of the HTMLInputElement to the focusable input element inside the component.
|
||||
|
@ -68,8 +68,7 @@ export interface CheckboxProps {
|
|||
'aria-label'?: string | undefined;
|
||||
}
|
||||
|
||||
export interface CheckboxSlots {
|
||||
}
|
||||
export interface CheckboxSlots {}
|
||||
|
||||
export declare type CheckboxEmits = {
|
||||
/**
|
||||
|
@ -81,24 +80,24 @@ export declare type CheckboxEmits = {
|
|||
* Callback to invoke on value click.
|
||||
* @param {MouseEvent} event - Browser event.
|
||||
*/
|
||||
'click': (event: MouseEvent) => void;
|
||||
click: (event: MouseEvent) => void;
|
||||
/**
|
||||
* Callback to invoke on value change.
|
||||
* @param {Event} event - Browser event.
|
||||
*/
|
||||
'change': (event: Event) => void;
|
||||
change: (event: Event) => void;
|
||||
/**
|
||||
* Callback to invoke on value change.
|
||||
* @param {boolean} value - New value.
|
||||
*/
|
||||
'input': (value: boolean) => void;
|
||||
}
|
||||
input: (value: boolean) => void;
|
||||
};
|
||||
|
||||
declare class Checkbox extends ClassComponent<CheckboxProps, CheckboxSlots, CheckboxEmits> { }
|
||||
declare class Checkbox extends ClassComponent<CheckboxProps, CheckboxSlots, CheckboxEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Checkbox: GlobalComponentConstructor<Checkbox>
|
||||
Checkbox: GlobalComponentConstructor<Checkbox>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +107,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Checkbox](https://www.primefaces.org/primevue/showcase/#/checkbox)
|
||||
* - [Checkbox](https://www.primefaces.org/primevue/checkbox)
|
||||
*
|
||||
*/
|
||||
export default Checkbox;
|
||||
|
|
|
@ -1,17 +1,34 @@
|
|||
<template>
|
||||
<div :class="containerClass" @click="onClick($event)">
|
||||
<div class="p-hidden-accessible">
|
||||
<input :id="inputId" ref="input" type="checkbox" :value="value" :class="inputClass" :style="inputStyle" :name="name" :checked="checked" :tabindex="tabindex" :disabled="disabled" :readonly="readonly" :required="required" :aria-labelledby="ariaLabelledby" :aria-label="ariaLabel"
|
||||
@focus="onFocus($event)" @blur="onBlur($event)" v-bind="inputProps">
|
||||
<input
|
||||
ref="input"
|
||||
:id="inputId"
|
||||
type="checkbox"
|
||||
:value="value"
|
||||
:class="inputClass"
|
||||
:style="inputStyle"
|
||||
:name="name"
|
||||
:checked="checked"
|
||||
:tabindex="tabindex"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
:aria-label="ariaLabel"
|
||||
@focus="onFocus($event)"
|
||||
@blur="onBlur($event)"
|
||||
v-bind="inputProps"
|
||||
/>
|
||||
</div>
|
||||
<div ref="box" :class="['p-checkbox-box', {'p-highlight': checked, 'p-disabled': disabled, 'p-focus': focused}]">
|
||||
<span :class="['p-checkbox-icon', {'pi pi-check': checked}]"></span>
|
||||
<div ref="box" :class="['p-checkbox-box', { 'p-highlight': checked, 'p-disabled': disabled, 'p-focus': focused }]">
|
||||
<span :class="['p-checkbox-icon', { 'pi pi-check': checked }]"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ObjectUtils} from 'primevue/utils';
|
||||
import { ObjectUtils } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'Checkbox',
|
||||
|
@ -48,13 +65,25 @@ export default {
|
|||
type: Number,
|
||||
default: null
|
||||
},
|
||||
inputId: null,
|
||||
inputClass: null,
|
||||
inputStyle: null,
|
||||
inputProps: null,
|
||||
inputId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
inputProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
'aria-labelledby': {
|
||||
type: String,
|
||||
default: null
|
||||
default: null
|
||||
},
|
||||
'aria-label': {
|
||||
type: String,
|
||||
|
@ -64,7 +93,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
focused: false
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onClick(event) {
|
||||
|
@ -73,12 +102,9 @@ export default {
|
|||
|
||||
if (this.binary) {
|
||||
newModelValue = this.checked ? this.falseValue : this.trueValue;
|
||||
}
|
||||
else {
|
||||
if (this.checked)
|
||||
newModelValue = this.modelValue.filter(val => !ObjectUtils.equals(val, this.value));
|
||||
else
|
||||
newModelValue = this.modelValue ? [...this.modelValue, this.value] : [this.value];
|
||||
} else {
|
||||
if (this.checked) newModelValue = this.modelValue.filter((val) => !ObjectUtils.equals(val, this.value));
|
||||
else newModelValue = this.modelValue ? [...this.modelValue, this.value] : [this.value];
|
||||
}
|
||||
|
||||
this.$emit('click', event);
|
||||
|
@ -103,12 +129,14 @@ export default {
|
|||
},
|
||||
containerClass() {
|
||||
return [
|
||||
'p-checkbox p-component', {
|
||||
'p-checkbox p-component',
|
||||
{
|
||||
'p-checkbox-checked': this.checked,
|
||||
'p-checkbox-disabled': this.disabled,
|
||||
'p-checkbox-focused': this.focused
|
||||
}];
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -37,14 +37,14 @@ export declare type ChipEmits = {
|
|||
* Callback to invoke when a chip is removed.
|
||||
* @param {Event} event - Browser event.
|
||||
*/
|
||||
'remove': (event: Event) => void;
|
||||
}
|
||||
remove: (event: Event) => void;
|
||||
};
|
||||
|
||||
declare class Chip extends ClassComponent<ChipProps, ChipSlots, ChipEmits> { }
|
||||
declare class Chip extends ClassComponent<ChipProps, ChipSlots, ChipEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Chip: GlobalComponentConstructor<Chip>
|
||||
Chip: GlobalComponentConstructor<Chip>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Chip](https://www.primefaces.org/primevue/showcase/#/chip)
|
||||
* - [Chip](https://www.primefaces.org/primevue/chip)
|
||||
*
|
||||
*/
|
||||
export default Chip;
|
||||
|
|
|
@ -22,7 +22,7 @@ describe('Chip.vue', () => {
|
|||
});
|
||||
|
||||
it('should close icon work', async () => {
|
||||
await wrapper.find('.p-chip-remove-icon').trigger('click')
|
||||
await wrapper.find('.p-chip-remove-icon').trigger('click');
|
||||
|
||||
expect(wrapper.find('.p-chip.p-component').exists()).toBe(false);
|
||||
});
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<template>
|
||||
<div :class="containerClass" v-if="visible">
|
||||
<div v-if="visible" :class="containerClass">
|
||||
<slot>
|
||||
<img :src="image" v-if="image">
|
||||
<span :class="iconClass" v-else-if="icon"></span>
|
||||
<div class="p-chip-text" v-if="label">{{label}}</div>
|
||||
<img v-if="image" :src="image" />
|
||||
<span v-else-if="icon" :class="iconClass"></span>
|
||||
<div v-if="label" class="p-chip-text">{{ label }}</div>
|
||||
</slot>
|
||||
<span v-if="removable" tabindex="0" :class="removeIconClass"
|
||||
@click="close" @keydown.enter="close"></span>
|
||||
<span v-if="removable" tabindex="0" :class="removeIconClass" @click="close" @keydown.enter="close"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -39,7 +38,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
visible: true
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close(event) {
|
||||
|
@ -49,9 +48,12 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-chip p-component', {
|
||||
'p-chip-image': this.image != null
|
||||
}];
|
||||
return [
|
||||
'p-chip p-component',
|
||||
{
|
||||
'p-chip-image': this.image != null
|
||||
}
|
||||
];
|
||||
},
|
||||
iconClass() {
|
||||
return ['p-chip-icon', this.icon];
|
||||
|
@ -60,7 +62,7 @@ export default {
|
|||
return ['p-chip-remove-icon', this.removeIcon];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -15,7 +15,7 @@ export interface ChipsAddEvent {
|
|||
/**
|
||||
* @extends ChipsAddEvent
|
||||
*/
|
||||
export interface ChipsRemoveEvent extends ChipsAddEvent { }
|
||||
export interface ChipsRemoveEvent extends ChipsAddEvent {}
|
||||
|
||||
export interface ChipsProps {
|
||||
/**
|
||||
|
@ -96,19 +96,19 @@ export declare type ChipsEmits = {
|
|||
* Callback to invoke when a chip is added.
|
||||
* @param {ChipsAddEvent} event - Custom add event.
|
||||
*/
|
||||
'add': (event: ChipsAddEvent) => void;
|
||||
add: (event: ChipsAddEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when a chip is removed.
|
||||
* @param {ChipsRemoveEvent} event - Custom remove event.
|
||||
*/
|
||||
'remove': (event: ChipsRemoveEvent) => void;
|
||||
}
|
||||
remove: (event: ChipsRemoveEvent) => void;
|
||||
};
|
||||
|
||||
declare class Chips extends ClassComponent<ChipsProps, ChipsSlots, ChipsEmits> { }
|
||||
declare class Chips extends ClassComponent<ChipsProps, ChipsSlots, ChipsEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Chips: GlobalComponentConstructor<Chips>
|
||||
Chips: GlobalComponentConstructor<Chips>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Chips](https://www.primefaces.org/primevue/showcase/#/chips)
|
||||
* - [Chips](https://www.primefaces.org/primevue/chips)
|
||||
*
|
||||
*/
|
||||
export default Chips;
|
||||
|
|
|
@ -18,10 +18,10 @@ describe('Chips.vue', () => {
|
|||
expect(wrapper.find('li.p-chips-input-token').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should add item', async() => {
|
||||
it('should add item', async () => {
|
||||
const addItem = jest.spyOn(wrapper.vm, 'addItem');
|
||||
|
||||
await wrapper.vm.addItem({},'PrimeVue', false);
|
||||
await wrapper.vm.addItem({}, 'PrimeVue', false);
|
||||
|
||||
await wrapper.setProps({ modelValue: ['PrimeVue'] });
|
||||
|
||||
|
|
|
@ -1,24 +1,58 @@
|
|||
<template>
|
||||
<div :class="containerClass">
|
||||
<ul ref="container" class="p-inputtext p-chips-multiple-container" tabindex="-1" role="listbox" aria-orientation="horizontal" :aria-labelledby="ariaLabelledby" :aria-label="ariaLabel" :aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@click="onWrapperClick()" @focus="onContainerFocus" @blur="onContainerBlur" @keydown="onContainerKeyDown">
|
||||
<li v-for="(val,i) of modelValue" :key="`${i}_${val}`" :id="id + '_chips_item_' + i" role="option" :class="['p-chips-token', {'p-focus': focusedIndex === i}]"
|
||||
:aria-label="val" :aria-selected="true" :aria-setsize="modelValue.length" :aria-posinset="i + 1">
|
||||
<ul
|
||||
ref="container"
|
||||
class="p-inputtext p-chips-multiple-container"
|
||||
tabindex="-1"
|
||||
role="listbox"
|
||||
aria-orientation="horizontal"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
:aria-label="ariaLabel"
|
||||
:aria-activedescendant="focused ? focusedOptionId : undefined"
|
||||
@click="onWrapperClick()"
|
||||
@focus="onContainerFocus"
|
||||
@blur="onContainerBlur"
|
||||
@keydown="onContainerKeyDown"
|
||||
>
|
||||
<li
|
||||
v-for="(val, i) of modelValue"
|
||||
:key="`${i}_${val}`"
|
||||
:id="id + '_chips_item_' + i"
|
||||
role="option"
|
||||
:class="['p-chips-token', { 'p-focus': focusedIndex === i }]"
|
||||
:aria-label="val"
|
||||
:aria-selected="true"
|
||||
:aria-setsize="modelValue.length"
|
||||
:aria-posinset="i + 1"
|
||||
>
|
||||
<slot name="chip" :value="val">
|
||||
<span class="p-chips-token-label">{{val}}</span>
|
||||
<span class="p-chips-token-label">{{ val }}</span>
|
||||
</slot>
|
||||
<span class="p-chips-token-icon pi pi-times-circle" @click="removeItem($event, i)" aria-hidden="true"></span>
|
||||
</li>
|
||||
<li class="p-chips-input-token" role="option">
|
||||
<input ref="input" type="text" :id="inputId" :class="inputClass" :style="inputStyle" :disabled="disabled || maxedOut" :placeholder="placeholder"
|
||||
@focus="onFocus($event)" @blur="onBlur($event)" @input="onInput" @keydown="onKeyDown($event)" @paste="onPaste($event)" v-bind="inputProps">
|
||||
<input
|
||||
ref="input"
|
||||
:id="inputId"
|
||||
type="text"
|
||||
:class="inputClass"
|
||||
:style="inputStyle"
|
||||
:disabled="disabled || maxedOut"
|
||||
:placeholder="placeholder"
|
||||
@focus="onFocus($event)"
|
||||
@blur="onBlur($event)"
|
||||
@input="onInput"
|
||||
@keydown="onKeyDown($event)"
|
||||
@paste="onPaste($event)"
|
||||
v-bind="inputProps"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {UniqueComponentId} from 'primevue/utils';
|
||||
import { UniqueComponentId } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'Chips',
|
||||
|
@ -48,17 +82,29 @@ export default {
|
|||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputId: null,
|
||||
inputClass: null,
|
||||
inputStyle: null,
|
||||
inputProps: null,
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
inputId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputClass: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
inputStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
inputProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
'aria-labelledby': {
|
||||
type: String,
|
||||
default: null
|
||||
default: null
|
||||
},
|
||||
'aria-label': {
|
||||
type: String,
|
||||
|
@ -89,39 +135,43 @@ export default {
|
|||
onBlur(event) {
|
||||
this.focused = false;
|
||||
this.focusedIndex = null;
|
||||
|
||||
if (this.addOnBlur) {
|
||||
this.addItem(event, event.target.value, false);
|
||||
}
|
||||
|
||||
this.$emit('blur', event);
|
||||
},
|
||||
onKeyDown(event) {
|
||||
const inputValue = event.target.value;
|
||||
|
||||
switch(event.code) {
|
||||
switch (event.code) {
|
||||
case 'Backspace':
|
||||
if (inputValue.length === 0 && this.modelValue && this.modelValue.length > 0) {
|
||||
if (this.focusedIndex !== null) {
|
||||
this.removeItem(event, this.focusedIndex);
|
||||
}
|
||||
else this.removeItem(event, this.modelValue.length - 1);
|
||||
} else this.removeItem(event, this.modelValue.length - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case 'Enter':
|
||||
if (inputValue && inputValue.trim().length && !this.maxedOut) {
|
||||
this.addItem(event, inputValue, true);
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case 'ArrowLeft':
|
||||
if (inputValue.length === 0 && this.modelValue && this.modelValue.length > 0) {
|
||||
this.$refs.container.focus();
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case 'ArrowRight':
|
||||
event.stopPropagation();
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this.separator) {
|
||||
|
@ -129,16 +179,19 @@ export default {
|
|||
this.addItem(event, inputValue, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
onPaste(event) {
|
||||
if (this.separator) {
|
||||
let pastedData = (event.clipboardData || window['clipboardData']).getData('Text');
|
||||
|
||||
if (pastedData) {
|
||||
let value = this.modelValue || [];
|
||||
let pastedValues = pastedData.split(this.separator);
|
||||
pastedValues = pastedValues.filter(val => (this.allowDuplicate || value.indexOf(val) === -1));
|
||||
|
||||
pastedValues = pastedValues.filter((val) => this.allowDuplicate || value.indexOf(val) === -1);
|
||||
value = [...value, ...pastedValues];
|
||||
this.updateModel(event, value, true);
|
||||
}
|
||||
|
@ -177,12 +230,10 @@ export default {
|
|||
},
|
||||
onArrowRightKeyOn() {
|
||||
if (this.inputValue.length === 0 && this.modelValue && this.modelValue.length > 0) {
|
||||
|
||||
if (this.focusedIndex === this.modelValue.length - 1) {
|
||||
this.focusedIndex = null;
|
||||
this.$refs.input.focus();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.focusedIndex++;
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +258,8 @@ export default {
|
|||
},
|
||||
addItem(event, item, preventDefault) {
|
||||
if (item && item.trim().length) {
|
||||
let value = this.modelValue ? [...this.modelValue]: [];
|
||||
let value = this.modelValue ? [...this.modelValue] : [];
|
||||
|
||||
if (this.allowDuplicate || value.indexOf(item) === -1) {
|
||||
value.push(item);
|
||||
this.updateModel(event, value, preventDefault);
|
||||
|
@ -221,6 +273,7 @@ export default {
|
|||
|
||||
let values = [...this.modelValue];
|
||||
const removedItem = values.splice(index, 1);
|
||||
|
||||
this.focusedIndex = null;
|
||||
this.$refs.input.focus();
|
||||
this.$emit('update:modelValue', values);
|
||||
|
@ -235,18 +288,21 @@ export default {
|
|||
return this.max && this.modelValue && this.max === this.modelValue.length;
|
||||
},
|
||||
containerClass() {
|
||||
return ['p-chips p-component p-inputwrapper', {
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused,
|
||||
'p-inputwrapper-filled': ((this.modelValue && this.modelValue.length) || (this.inputValue && this.inputValue.length)),
|
||||
'p-inputwrapper-focus': this.focused
|
||||
}];
|
||||
return [
|
||||
'p-chips p-component p-inputwrapper',
|
||||
{
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused,
|
||||
'p-inputwrapper-filled': (this.modelValue && this.modelValue.length) || (this.inputValue && this.inputValue.length),
|
||||
'p-inputwrapper-focus': this.focused
|
||||
}
|
||||
];
|
||||
},
|
||||
focusedOptionId() {
|
||||
return this.focusedIndex !== null ? `${this.id}_chips_item_${this.focusedIndex}` : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -65,8 +65,7 @@ export interface ColorPickerProps {
|
|||
appendTo?: ColorPickerAppendToType;
|
||||
}
|
||||
|
||||
export interface ColorPickerSlots {
|
||||
}
|
||||
export interface ColorPickerSlots {}
|
||||
|
||||
export declare type ColorPickerEmits = {
|
||||
/**
|
||||
|
@ -75,25 +74,25 @@ export declare type ColorPickerEmits = {
|
|||
*/
|
||||
'update:modelValue': (value: any) => void;
|
||||
/**
|
||||
* Callback to invoke when a chip is added.
|
||||
* @param {ColorPickerChangeEvent} event - Custom add event.
|
||||
*/
|
||||
'change': (event: ColorPickerChangeEvent) => void;
|
||||
* Callback to invoke when a chip is added.
|
||||
* @param {ColorPickerChangeEvent} event - Custom add event.
|
||||
*/
|
||||
change: (event: ColorPickerChangeEvent) => void;
|
||||
/**
|
||||
* Callback to invoke when input is cleared by the user.
|
||||
*/
|
||||
'show': () => void;
|
||||
show: () => void;
|
||||
/**
|
||||
* Callback to invoke when input is cleared by the user.
|
||||
*/
|
||||
'hide': () => void;
|
||||
}
|
||||
hide: () => void;
|
||||
};
|
||||
|
||||
declare class ColorPicker extends ClassComponent<ColorPickerProps, ColorPickerSlots, ColorPickerEmits> { }
|
||||
declare class ColorPicker extends ClassComponent<ColorPickerProps, ColorPickerSlots, ColorPickerEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
ColorPicker: GlobalComponentConstructor<ColorPicker>
|
||||
ColorPicker: GlobalComponentConstructor<ColorPicker>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +102,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [ColorPicker](https://www.primefaces.org/primevue/showcase/#/colorpicker)
|
||||
* - [ColorPicker](https://www.primefaces.org/primevue/colorpicker)
|
||||
*
|
||||
*/
|
||||
export default ColorPicker;
|
||||
|
|
|
@ -24,7 +24,7 @@ describe('ColorPicker.vue', () => {
|
|||
expect(wrapper.find('.p-colorpicker-preview.p-inputtext').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should input click triggered', async() => {
|
||||
it('should input click triggered', async () => {
|
||||
const input = wrapper.find('.p-colorpicker-preview.p-inputtext');
|
||||
const onInputClick = jest.spyOn(wrapper.vm, 'onInputClick');
|
||||
|
||||
|
@ -36,15 +36,15 @@ describe('ColorPicker.vue', () => {
|
|||
expect(wrapper.find('.p-colorpicker-hue').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should mouse events triggered', async() => {
|
||||
it('should mouse events triggered', async () => {
|
||||
const input = wrapper.find('.p-colorpicker-preview.p-inputtext');
|
||||
|
||||
await input.trigger('click');
|
||||
|
||||
const onColorMousedown = jest.spyOn(wrapper.vm, 'onColorMousedown');
|
||||
const onHueMousedown = jest.spyOn(wrapper.vm, 'onHueMousedown');
|
||||
const event = { pageX: 100, pageY: 120, preventDefault: () => {}};
|
||||
const event2 = { pageX: 70, pageY: 20, preventDefault: () => {}};
|
||||
const event = { pageX: 100, pageY: 120, preventDefault: () => {} };
|
||||
const event2 = { pageX: 70, pageY: 20, preventDefault: () => {} };
|
||||
|
||||
wrapper.vm.onColorMousedown(event);
|
||||
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
<template>
|
||||
<div ref="container" :class="containerClass">
|
||||
<input ref="input" type="text" :class="inputClass" readonly="readonly" :tabindex="tabindex" :disabled="disabled"
|
||||
@click="onInputClick" @keydown="onInputKeydown" v-if="!inline"/>
|
||||
<input v-if="!inline" ref="input" type="text" :class="inputClass" readonly="readonly" :tabindex="tabindex" :disabled="disabled" @click="onInputClick" @keydown="onInputKeydown" />
|
||||
<Portal :appendTo="appendTo" :disabled="inline">
|
||||
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
|
||||
<div :ref="pickerRef" :class="pickerClass" v-if="inline ? true : overlayVisible" @click="onOverlayClick">
|
||||
<div v-if="inline ? true : overlayVisible" :ref="pickerRef" :class="pickerClass" @click="onOverlayClick">
|
||||
<div class="p-colorpicker-content">
|
||||
<div :ref="colorSelectorRef" class="p-colorpicker-color-selector" @mousedown="onColorMousedown($event)"
|
||||
@touchstart="onColorDragStart($event)" @touchmove="onDrag($event)" @touchend="onDragEnd()">
|
||||
<div :ref="colorSelectorRef" class="p-colorpicker-color-selector" @mousedown="onColorMousedown($event)" @touchstart="onColorDragStart($event)" @touchmove="onDrag($event)" @touchend="onDragEnd()">
|
||||
<div class="p-colorpicker-color">
|
||||
<div :ref="colorHandleRef" class="p-colorpicker-color-handle"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div :ref="hueViewRef" class="p-colorpicker-hue" @mousedown="onHueMousedown($event)"
|
||||
@touchstart="onHueDragStart($event)" @touchmove="onDrag($event)" @touchend="onDragEnd()">
|
||||
<div :ref="hueViewRef" class="p-colorpicker-hue" @mousedown="onHueMousedown($event)" @touchstart="onHueDragStart($event)" @touchmove="onDrag($event)" @touchend="onDragEnd()">
|
||||
<div :ref="hueHandleRef" class="p-colorpicker-hue-handle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,7 +21,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
|
||||
import { ConnectedOverlayScrollHandler, DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import Portal from 'primevue/portal';
|
||||
|
||||
|
@ -89,6 +86,17 @@ export default {
|
|||
colorHandle: null,
|
||||
hueView: null,
|
||||
hueHandle: null,
|
||||
watch: {
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(newValue) {
|
||||
this.hsbValue = this.toHSB(newValue);
|
||||
|
||||
if (this.selfUpdate) this.selfUpdate = false;
|
||||
else this.updateUI();
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.unbindOutsideClickListener();
|
||||
this.unbindDragListeners();
|
||||
|
@ -108,26 +116,14 @@ export default {
|
|||
mounted() {
|
||||
this.updateUI();
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(newValue) {
|
||||
this.hsbValue = this.toHSB(newValue);
|
||||
|
||||
if (this.selfUpdate)
|
||||
this.selfUpdate = false;
|
||||
else
|
||||
this.updateUI();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pickColor(event) {
|
||||
let rect = this.colorSelector.getBoundingClientRect();
|
||||
let top = rect.top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
|
||||
let left = rect.left + document.body.scrollLeft;
|
||||
let saturation = Math.floor(100 * (Math.max(0, Math.min(150, ((event.pageX || event.changedTouches[0].pageX)- left)))) / 150);
|
||||
let brightness = Math.floor(100 * (150 - Math.max(0, Math.min(150, ((event.pageY || event.changedTouches[0].pageY) - top)))) / 150);
|
||||
let saturation = Math.floor((100 * Math.max(0, Math.min(150, (event.pageX || event.changedTouches[0].pageX) - left))) / 150);
|
||||
let brightness = Math.floor((100 * (150 - Math.max(0, Math.min(150, (event.pageY || event.changedTouches[0].pageY) - top)))) / 150);
|
||||
|
||||
this.hsbValue = this.validateHSB({
|
||||
h: this.hsbValue.h,
|
||||
s: saturation,
|
||||
|
@ -138,12 +134,13 @@ export default {
|
|||
this.updateColorHandle();
|
||||
this.updateInput();
|
||||
this.updateModel();
|
||||
this.$emit('change', {event: event, value: this.modelValue});
|
||||
this.$emit('change', { event: event, value: this.modelValue });
|
||||
},
|
||||
pickHue(event) {
|
||||
let top = this.hueView.getBoundingClientRect().top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
|
||||
|
||||
this.hsbValue = this.validateHSB({
|
||||
h: Math.floor(360 * (150 - Math.max(0, Math.min(150, ((event.pageY || event.changedTouches[0].pageY) - top)))) / 150),
|
||||
h: Math.floor((360 * (150 - Math.max(0, Math.min(150, (event.pageY || event.changedTouches[0].pageY) - top)))) / 150),
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
|
@ -153,25 +150,25 @@ export default {
|
|||
this.updateHue();
|
||||
this.updateModel();
|
||||
this.updateInput();
|
||||
this.$emit('change', {event: event, value: this.modelValue});
|
||||
this.$emit('change', { event: event, value: this.modelValue });
|
||||
},
|
||||
updateModel() {
|
||||
switch(this.format) {
|
||||
switch (this.format) {
|
||||
case 'hex':
|
||||
this.$emit('update:modelValue', this.HSBtoHEX(this.hsbValue));
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'rgb':
|
||||
this.$emit('update:modelValue', this.HSBtoRGB(this.hsbValue));
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'hsb':
|
||||
this.$emit('update:modelValue', this.hsbValue);
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
//NoOp
|
||||
break;
|
||||
break;
|
||||
}
|
||||
},
|
||||
updateColorSelector() {
|
||||
|
@ -181,18 +178,19 @@ export default {
|
|||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
|
||||
this.colorSelector.style.backgroundColor = '#' + this.HSBtoHEX(hsbValue);
|
||||
}
|
||||
},
|
||||
updateColorHandle() {
|
||||
if (this.colorHandle) {
|
||||
this.colorHandle.style.left = Math.floor(150 * this.hsbValue.s / 100) + 'px';
|
||||
this.colorHandle.style.top = Math.floor(150 * (100 - this.hsbValue.b) / 100) + 'px';
|
||||
this.colorHandle.style.left = Math.floor((150 * this.hsbValue.s) / 100) + 'px';
|
||||
this.colorHandle.style.top = Math.floor((150 * (100 - this.hsbValue.b)) / 100) + 'px';
|
||||
}
|
||||
},
|
||||
updateHue() {
|
||||
if (this.hueHandle) {
|
||||
this.hueHandle.style.top = Math.floor(150 - (150 * this.hsbValue.h / 360)) + 'px';
|
||||
this.hueHandle.style.top = Math.floor(150 - (150 * this.hsbValue.h) / 360) + 'px';
|
||||
}
|
||||
},
|
||||
updateInput() {
|
||||
|
@ -222,19 +220,24 @@ export default {
|
|||
},
|
||||
validateHEX(hex) {
|
||||
var len = 6 - hex.length;
|
||||
|
||||
if (len > 0) {
|
||||
var o = [];
|
||||
for (var i=0; i<len; i++) {
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
o.push('0');
|
||||
}
|
||||
|
||||
o.push(hex);
|
||||
hex = o.join('');
|
||||
}
|
||||
|
||||
return hex;
|
||||
},
|
||||
HEXtoRGB(hex) {
|
||||
let hexValue = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
|
||||
return {r: hexValue >> 16, g: (hexValue & 0x00FF00) >> 8, b: (hexValue & 0x0000FF)};
|
||||
let hexValue = parseInt(hex.indexOf('#') > -1 ? hex.substring(1) : hex, 16);
|
||||
|
||||
return { r: hexValue >> 16, g: (hexValue & 0x00ff00) >> 8, b: hexValue & 0x0000ff };
|
||||
},
|
||||
HEXtoHSB(hex) {
|
||||
return this.RGBtoHSB(this.HEXtoRGB(hex));
|
||||
|
@ -248,8 +251,10 @@ export default {
|
|||
var min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||
var max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||
var delta = max - min;
|
||||
|
||||
hsb.b = max;
|
||||
hsb.s = max !== 0 ? 255 * delta / max : 0;
|
||||
hsb.s = max !== 0 ? (255 * delta) / max : 0;
|
||||
|
||||
if (hsb.s !== 0) {
|
||||
if (rgb.r === max) {
|
||||
hsb.h = (rgb.g - rgb.b) / delta;
|
||||
|
@ -261,49 +266,76 @@ export default {
|
|||
} else {
|
||||
hsb.h = -1;
|
||||
}
|
||||
|
||||
hsb.h *= 60;
|
||||
|
||||
if (hsb.h < 0) {
|
||||
hsb.h += 360;
|
||||
}
|
||||
hsb.s *= 100/255;
|
||||
hsb.b *= 100/255;
|
||||
|
||||
hsb.s *= 100 / 255;
|
||||
hsb.b *= 100 / 255;
|
||||
|
||||
return hsb;
|
||||
},
|
||||
HSBtoRGB(hsb) {
|
||||
var rgb = {
|
||||
r: null, g: null, b: null
|
||||
r: null,
|
||||
g: null,
|
||||
b: null
|
||||
};
|
||||
var h = Math.round(hsb.h);
|
||||
var s = Math.round(hsb.s*255/100);
|
||||
var v = Math.round(hsb.b*255/100);
|
||||
var s = Math.round((hsb.s * 255) / 100);
|
||||
var v = Math.round((hsb.b * 255) / 100);
|
||||
|
||||
if (s === 0) {
|
||||
rgb = {
|
||||
r: v,
|
||||
g: v,
|
||||
b: v
|
||||
};
|
||||
} else {
|
||||
var t1 = v;
|
||||
var t2 = ((255 - s) * v) / 255;
|
||||
var t3 = ((t1 - t2) * (h % 60)) / 60;
|
||||
|
||||
if (h === 360) h = 0;
|
||||
|
||||
if (h < 60) {
|
||||
rgb.r = t1;
|
||||
rgb.b = t2;
|
||||
rgb.g = t2 + t3;
|
||||
} else if (h < 120) {
|
||||
rgb.g = t1;
|
||||
rgb.b = t2;
|
||||
rgb.r = t1 - t3;
|
||||
} else if (h < 180) {
|
||||
rgb.g = t1;
|
||||
rgb.r = t2;
|
||||
rgb.b = t2 + t3;
|
||||
} else if (h < 240) {
|
||||
rgb.b = t1;
|
||||
rgb.r = t2;
|
||||
rgb.g = t1 - t3;
|
||||
} else if (h < 300) {
|
||||
rgb.b = t1;
|
||||
rgb.g = t2;
|
||||
rgb.r = t2 + t3;
|
||||
} else if (h < 360) {
|
||||
rgb.r = t1;
|
||||
rgb.g = t2;
|
||||
rgb.b = t1 - t3;
|
||||
} else {
|
||||
rgb.r = 0;
|
||||
rgb.g = 0;
|
||||
rgb.b = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t1 = v;
|
||||
var t2 = (255-s)*v/255;
|
||||
var t3 = (t1-t2)*(h%60)/60;
|
||||
if (h===360) h = 0;
|
||||
if (h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3}
|
||||
else if (h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3}
|
||||
else if (h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3}
|
||||
else if (h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3}
|
||||
else if (h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3}
|
||||
else if (h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3}
|
||||
else {rgb.r=0; rgb.g=0; rgb.b=0}
|
||||
}
|
||||
return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
|
||||
|
||||
return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) };
|
||||
},
|
||||
RGBtoHEX(rgb) {
|
||||
var hex = [
|
||||
rgb.r.toString(16),
|
||||
rgb.g.toString(16),
|
||||
rgb.b.toString(16)
|
||||
];
|
||||
var hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
|
||||
|
||||
for (var key in hex) {
|
||||
if (hex[key].length === 1) {
|
||||
|
@ -323,21 +355,20 @@ export default {
|
|||
switch (this.format) {
|
||||
case 'hex':
|
||||
hsb = this.HEXtoHSB(value);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'rgb':
|
||||
hsb = this.RGBtoHSB(value);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'hsb':
|
||||
hsb = value;
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
hsb = this.HEXtoHSB(this.defaultColor);
|
||||
}
|
||||
|
||||
|
@ -369,10 +400,8 @@ export default {
|
|||
}
|
||||
},
|
||||
alignOverlay() {
|
||||
if (this.appendTo === 'self')
|
||||
DomHandler.relativePosition(this.picker, this.$refs.input);
|
||||
else
|
||||
DomHandler.absolutePosition(this.picker, this.$refs.input);
|
||||
if (this.appendTo === 'self') DomHandler.relativePosition(this.picker, this.$refs.input);
|
||||
else DomHandler.absolutePosition(this.picker, this.$refs.input);
|
||||
},
|
||||
onInputClick() {
|
||||
if (this.disabled) {
|
||||
|
@ -382,22 +411,22 @@ export default {
|
|||
this.overlayVisible = !this.overlayVisible;
|
||||
},
|
||||
onInputKeydown(event) {
|
||||
switch(event.which) {
|
||||
switch (event.which) {
|
||||
//space
|
||||
case 32:
|
||||
this.overlayVisible = !this.overlayVisible;
|
||||
event.preventDefault();
|
||||
break;
|
||||
break;
|
||||
|
||||
//escape and tab
|
||||
case 27:
|
||||
case 9:
|
||||
this.overlayVisible = false;
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
//NoOp
|
||||
break;
|
||||
break;
|
||||
}
|
||||
},
|
||||
onColorMousedown(event) {
|
||||
|
@ -470,6 +499,7 @@ export default {
|
|||
this.overlayVisible = false;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
|
@ -502,6 +532,7 @@ export default {
|
|||
this.overlayVisible = false;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', this.resizeListener);
|
||||
}
|
||||
},
|
||||
|
@ -536,7 +567,7 @@ export default {
|
|||
}
|
||||
},
|
||||
pickerRef(el) {
|
||||
this.picker = el
|
||||
this.picker = el;
|
||||
},
|
||||
colorSelectorRef(el) {
|
||||
this.colorSelector = el;
|
||||
|
@ -566,23 +597,28 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-colorpicker p-component', {'p-colorpicker-overlay': !this.inline}];
|
||||
return ['p-colorpicker p-component', { 'p-colorpicker-overlay': !this.inline }];
|
||||
},
|
||||
inputClass() {
|
||||
return ['p-colorpicker-preview p-inputtext', {'p-disabled': this.disabled}];
|
||||
return ['p-colorpicker-preview p-inputtext', { 'p-disabled': this.disabled }];
|
||||
},
|
||||
pickerClass() {
|
||||
return ['p-colorpicker-panel', this.panelClass, {
|
||||
'p-colorpicker-overlay-panel': !this.inline, 'p-disabled': this.disabled,
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}];
|
||||
return [
|
||||
'p-colorpicker-panel',
|
||||
this.panelClass,
|
||||
{
|
||||
'p-colorpicker-overlay-panel': !this.inline,
|
||||
'p-disabled': this.disabled,
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'Portal': Portal
|
||||
Portal: Portal
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -627,22 +663,22 @@ export default {
|
|||
}
|
||||
|
||||
.p-colorpicker-panel .p-colorpicker-color {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.p-colorpicker-panel .p-colorpicker-color-handle {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 150px;
|
||||
border-radius: 100%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
margin: -5px 0 0 -5px;
|
||||
cursor: pointer;
|
||||
opacity: .85;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 150px;
|
||||
border-radius: 100%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
margin: -5px 0 0 -5px;
|
||||
cursor: pointer;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.p-colorpicker-panel .p-colorpicker-hue {
|
||||
|
@ -651,20 +687,20 @@ export default {
|
|||
top: 8px;
|
||||
left: 167px;
|
||||
position: absolute;
|
||||
opacity: .85;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.p-colorpicker-panel .p-colorpicker-hue-handle {
|
||||
position: absolute;
|
||||
top: 150px;
|
||||
left: 0px;
|
||||
width: 21px;
|
||||
margin-left: -2px;
|
||||
margin-top: -5px;
|
||||
height: 10px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
opacity: .85;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 150px;
|
||||
left: 0px;
|
||||
width: 21px;
|
||||
margin-left: -2px;
|
||||
margin-top: -5px;
|
||||
height: 10px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
opacity: 0.85;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -464,14 +464,13 @@ export interface ColumnSlots {
|
|||
}) => VNode[];
|
||||
}
|
||||
|
||||
export declare type ColumnEmits = {
|
||||
}
|
||||
export declare type ColumnEmits = {};
|
||||
|
||||
declare class Column extends ClassComponent<ColumnProps, ColumnSlots, ColumnEmits> { }
|
||||
declare class Column extends ClassComponent<ColumnProps, ColumnSlots, ColumnEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Column: GlobalComponentConstructor<Column>
|
||||
Column: GlobalComponentConstructor<Column>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,8 +480,8 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [DataTable](https://www.primefaces.org/primevue/showcase/#/datatable)
|
||||
* - [TreeTable](https://www.primefaces.org/primevue/showcase/#/treetable)
|
||||
* - [DataTable](https://www.primefaces.org/primevue/datatable)
|
||||
* - [TreeTable](https://www.primefaces.org/primevue/treetable)
|
||||
*
|
||||
*/
|
||||
export default Column;
|
||||
|
|
|
@ -182,5 +182,5 @@ export default {
|
|||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -9,17 +9,15 @@ export interface ColumnGroupProps {
|
|||
type?: ColumnGroupType;
|
||||
}
|
||||
|
||||
export interface ColumnGroupSlots {
|
||||
}
|
||||
export interface ColumnGroupSlots {}
|
||||
|
||||
export declare type ColumnGroupEmits = {
|
||||
}
|
||||
export declare type ColumnGroupEmits = {};
|
||||
|
||||
declare class ColumnGroup extends ClassComponent<ColumnGroupProps, ColumnGroupSlots, ColumnGroupEmits> { }
|
||||
declare class ColumnGroup extends ClassComponent<ColumnGroupProps, ColumnGroupSlots, ColumnGroupEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
ColumnGroup: GlobalComponentConstructor<ColumnGroup>
|
||||
ColumnGroup: GlobalComponentConstructor<ColumnGroup>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +27,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [ColumnGroup](https://www.primefaces.org/primevue/showcase/#/datatable/colgroup)
|
||||
* - [ColumnGroup](https://www.primefaces.org/primevue/datatable/colgroup)
|
||||
*
|
||||
*/
|
||||
export default ColumnGroup;
|
||||
|
|
|
@ -10,5 +10,5 @@ export default {
|
|||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -24,6 +24,8 @@ interface PrimeVueLocaleAriaOptions {
|
|||
selectAll?: string;
|
||||
unselectAll?: string;
|
||||
close?: string;
|
||||
previous?: string;
|
||||
next?: string;
|
||||
}
|
||||
|
||||
interface PrimeVueLocaleOptions {
|
||||
|
@ -101,7 +103,7 @@ declare module 'vue/types/vue' {
|
|||
interface Vue {
|
||||
$primevue: {
|
||||
config: PrimeVueConfiguration;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,6 +111,6 @@ declare module '@vue/runtime-core' {
|
|||
interface ComponentCustomProperties {
|
||||
$primevue: {
|
||||
config: PrimeVueConfiguration;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {reactive,inject} from 'vue';
|
||||
import {FilterMatchMode} from 'primevue/api';
|
||||
import { reactive, inject } from 'vue';
|
||||
import { FilterMatchMode } from 'primevue/api';
|
||||
|
||||
const defaultOptions = {
|
||||
ripple: false,
|
||||
|
@ -31,11 +31,11 @@ const defaultOptions = {
|
|||
choose: 'Choose',
|
||||
upload: 'Upload',
|
||||
cancel: 'Cancel',
|
||||
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
||||
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
||||
dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"],
|
||||
monthNames: ["January","February","March","April","May","June","July","August","September","October","November","December"],
|
||||
monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||||
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||
dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
|
||||
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
chooseYear: 'Choose Year',
|
||||
chooseMonth: 'Choose Month',
|
||||
chooseDate: 'Choose Date',
|
||||
|
@ -75,32 +75,15 @@ const defaultOptions = {
|
|||
stars: '{star} stars',
|
||||
selectAll: 'All items selected',
|
||||
unselectAll: 'All items unselected',
|
||||
close: 'Close'
|
||||
close: 'Close',
|
||||
previous: 'Previous',
|
||||
next: 'Next'
|
||||
}
|
||||
},
|
||||
filterMatchModeOptions: {
|
||||
text: [
|
||||
FilterMatchMode.STARTS_WITH,
|
||||
FilterMatchMode.CONTAINS,
|
||||
FilterMatchMode.NOT_CONTAINS,
|
||||
FilterMatchMode.ENDS_WITH,
|
||||
FilterMatchMode.EQUALS,
|
||||
FilterMatchMode.NOT_EQUALS
|
||||
],
|
||||
numeric: [
|
||||
FilterMatchMode.EQUALS,
|
||||
FilterMatchMode.NOT_EQUALS,
|
||||
FilterMatchMode.LESS_THAN,
|
||||
FilterMatchMode.LESS_THAN_OR_EQUAL_TO,
|
||||
FilterMatchMode.GREATER_THAN,
|
||||
FilterMatchMode.GREATER_THAN_OR_EQUAL_TO
|
||||
],
|
||||
date: [
|
||||
FilterMatchMode.DATE_IS,
|
||||
FilterMatchMode.DATE_IS_NOT,
|
||||
FilterMatchMode.DATE_BEFORE,
|
||||
FilterMatchMode.DATE_AFTER
|
||||
]
|
||||
text: [FilterMatchMode.STARTS_WITH, FilterMatchMode.CONTAINS, FilterMatchMode.NOT_CONTAINS, FilterMatchMode.ENDS_WITH, FilterMatchMode.EQUALS, FilterMatchMode.NOT_EQUALS],
|
||||
numeric: [FilterMatchMode.EQUALS, FilterMatchMode.NOT_EQUALS, FilterMatchMode.LESS_THAN, FilterMatchMode.LESS_THAN_OR_EQUAL_TO, FilterMatchMode.GREATER_THAN, FilterMatchMode.GREATER_THAN_OR_EQUAL_TO],
|
||||
date: [FilterMatchMode.DATE_IS, FilterMatchMode.DATE_IS_NOT, FilterMatchMode.DATE_BEFORE, FilterMatchMode.DATE_AFTER]
|
||||
},
|
||||
zIndex: {
|
||||
modal: 1100,
|
||||
|
@ -114,6 +97,7 @@ const PrimeVueSymbol = Symbol();
|
|||
|
||||
export function usePrimeVue() {
|
||||
const PrimeVue = inject(PrimeVueSymbol);
|
||||
|
||||
if (!PrimeVue) {
|
||||
throw new Error('PrimeVue is not installed!');
|
||||
}
|
||||
|
@ -123,10 +107,11 @@ export function usePrimeVue() {
|
|||
|
||||
export default {
|
||||
install: (app, options) => {
|
||||
let configOptions = options ? {...defaultOptions, ...options} : {...defaultOptions};
|
||||
let configOptions = options ? { ...defaultOptions, ...options } : { ...defaultOptions };
|
||||
const PrimeVue = {
|
||||
config: reactive(configOptions)
|
||||
};
|
||||
|
||||
app.config.globalProperties.$primevue = PrimeVue;
|
||||
app.provide(PrimeVueSymbol, PrimeVue);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import {EventBus} from 'primevue/utils';
|
||||
import { EventBus } from 'primevue/utils';
|
||||
|
||||
export default EventBus();
|
|
@ -39,6 +39,10 @@ export interface ConfirmationOptions {
|
|||
* Callback to execute when action is rejected.
|
||||
*/
|
||||
reject?: () => void;
|
||||
/**
|
||||
* Callback to execute when dialog is hidden.
|
||||
*/
|
||||
onHide?: () => void;
|
||||
/**
|
||||
* Label of the accept button. Defaults to PrimeVue Locale configuration.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import ConfirmationEventBus from 'primevue/confirmationeventbus';
|
||||
import {PrimeVueConfirmSymbol} from 'primevue/useconfirm';
|
||||
import { PrimeVueConfirmSymbol } from 'primevue/useconfirm';
|
||||
|
||||
export default {
|
||||
install: (app) => {
|
||||
|
@ -11,6 +11,7 @@ export default {
|
|||
ConfirmationEventBus.emit('close');
|
||||
}
|
||||
};
|
||||
|
||||
app.config.globalProperties.$confirm = ConfirmationService;
|
||||
app.provide(PrimeVueConfirmSymbol, ConfirmationService);
|
||||
}
|
||||
|
|
|
@ -38,19 +38,16 @@ export interface ConfirmDialogSlots {
|
|||
* Custom message template.
|
||||
* @param {Object} scope - message slot's params.
|
||||
*/
|
||||
message: (scope: {
|
||||
message: ConfirmationOptions;
|
||||
}) => VNode[];
|
||||
message: (scope: { message: ConfirmationOptions }) => VNode[];
|
||||
}
|
||||
|
||||
export declare type ConfirmDialogEmits = {
|
||||
}
|
||||
export declare type ConfirmDialogEmits = {};
|
||||
|
||||
declare class ConfirmDialog extends ClassComponent<ConfirmDialogProps, ConfirmDialogSlots, ConfirmDialogEmits> { }
|
||||
declare class ConfirmDialog extends ClassComponent<ConfirmDialogProps, ConfirmDialogSlots, ConfirmDialogEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
ConfirmDialog: GlobalComponentConstructor<ConfirmDialog>
|
||||
ConfirmDialog: GlobalComponentConstructor<ConfirmDialog>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +62,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [ConfirmDialog](https://www.primefaces.org/primevue/showcase/#/confirmdialog)
|
||||
* - [ConfirmDialog](https://www.primefaces.org/primevue/confirmdialog)
|
||||
*
|
||||
*/
|
||||
export default ConfirmDialog;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import PrimeVue from '@/components/config/PrimeVue';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import ConfirmDialog from './ConfirmDialog.vue';
|
||||
|
||||
describe('ConfirmDialog', () => {
|
||||
it('should exist', async() => {
|
||||
it('should exist', async () => {
|
||||
const wrapper = mount(ConfirmDialog, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true,
|
||||
transition: false
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -19,7 +19,7 @@ describe('ConfirmDialog', () => {
|
|||
header: 'Confirmation',
|
||||
icon: 'pi pi-exclamation-triangle'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -31,10 +31,10 @@ describe('ConfirmDialog', () => {
|
|||
|
||||
await wrapper.vm.reject();
|
||||
|
||||
expect(wrapper.find('.p-dialog-mask .p-dialog.p-component').exists()).toBe(false);
|
||||
expect(wrapper.find('.p-dialog-mask .p-dialog.p-component').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should dialog trigger the accept function', async() => {
|
||||
it('should dialog trigger the accept function', async () => {
|
||||
const wrapper = mount(ConfirmDialog, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
|
@ -50,14 +50,15 @@ describe('ConfirmDialog', () => {
|
|||
header: 'Confirmation',
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
accept: () => {
|
||||
console.log('accept')
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('accept');
|
||||
},
|
||||
reject: () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('reject');
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -72,7 +73,7 @@ describe('ConfirmDialog', () => {
|
|||
expect(acceptTriggered).toBeCalled();
|
||||
});
|
||||
|
||||
it('should dialog trigger the reject function', async() => {
|
||||
it('should dialog trigger the reject function', async () => {
|
||||
const wrapper = mount(ConfirmDialog, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
|
@ -88,14 +89,15 @@ describe('ConfirmDialog', () => {
|
|||
header: 'Confirmation',
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
accept: () => {
|
||||
console.log('accept')
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('accept');
|
||||
},
|
||||
reject: () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('reject');
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -110,7 +112,7 @@ describe('ConfirmDialog', () => {
|
|||
expect(rejectTriggered).toBeCalled();
|
||||
});
|
||||
|
||||
it('should dialog close button work', async() => {
|
||||
it('should dialog close button work', async () => {
|
||||
const wrapper = mount(ConfirmDialog, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
|
@ -126,7 +128,7 @@ describe('ConfirmDialog', () => {
|
|||
header: 'Confirmation',
|
||||
icon: 'pi pi-exclamation-triangle'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -136,7 +138,7 @@ describe('ConfirmDialog', () => {
|
|||
|
||||
await dialogCloseBtn.trigger('click');
|
||||
|
||||
expect(wrapper.find('.p-dialog-mask .p-dialog.p-component').exists()).toBe(false);
|
||||
expect(wrapper.find('.p-dialog-mask .p-dialog.p-component').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should position work', async () => {
|
||||
|
@ -157,7 +159,7 @@ describe('ConfirmDialog', () => {
|
|||
icon: 'pi pi-info-circle',
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
<template>
|
||||
<CDialog v-model:visible="visible" :modal="true" :header="header" :blockScroll="blockScroll" :position="position" class="p-confirm-dialog"
|
||||
:breakpoints="breakpoints" :closeOnEscape="closeOnEscape">
|
||||
<CDialog v-model:visible="visible" :modal="true" :header="header" :blockScroll="blockScroll" :position="position" class="p-confirm-dialog" :breakpoints="breakpoints" :closeOnEscape="closeOnEscape" @update:visible="onHide">
|
||||
<template v-if="!$slots.message">
|
||||
<i :class="iconClass" />
|
||||
<span class="p-confirm-dialog-message">{{ message }}</span>
|
||||
</template>
|
||||
<component v-else :is="$slots.message" :message="confirmation"></component>
|
||||
<template #footer>
|
||||
<CDButton :label="rejectLabel" :icon="rejectIcon" :class="rejectClass" @click="reject()" :autofocus="autoFocusReject"/>
|
||||
<CDButton :label="rejectLabel" :icon="rejectIcon" :class="rejectClass" @click="reject()" :autofocus="autoFocusReject" />
|
||||
<CDButton :label="acceptLabel" :icon="acceptIcon" :class="acceptClass" @click="accept()" :autofocus="autoFocusAccept" />
|
||||
</template>
|
||||
</CDialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Button from 'primevue/button';
|
||||
import ConfirmationEventBus from 'primevue/confirmationeventbus';
|
||||
import Dialog from 'primevue/dialog';
|
||||
import Button from 'primevue/button';
|
||||
|
||||
export default {
|
||||
name: 'ConfirmDialog',
|
||||
|
@ -32,8 +31,8 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
confirmation: null,
|
||||
}
|
||||
confirmation: null
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.confirmListener = (options) => {
|
||||
|
@ -51,6 +50,7 @@ export default {
|
|||
this.visible = false;
|
||||
this.confirmation = null;
|
||||
};
|
||||
|
||||
ConfirmationEventBus.on('confirm', this.confirmListener);
|
||||
ConfirmationEventBus.on('close', this.closeListener);
|
||||
},
|
||||
|
@ -71,6 +71,13 @@ export default {
|
|||
this.confirmation.reject();
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
},
|
||||
onHide() {
|
||||
if (this.confirmation.onHide) {
|
||||
this.confirmation.onHide();
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
}
|
||||
},
|
||||
|
@ -91,10 +98,10 @@ export default {
|
|||
return ['p-confirm-dialog-icon', this.confirmation ? this.confirmation.icon : null];
|
||||
},
|
||||
acceptLabel() {
|
||||
return this.confirmation ? (this.confirmation.acceptLabel || this.$primevue.config.locale.accept) : null;
|
||||
return this.confirmation ? this.confirmation.acceptLabel || this.$primevue.config.locale.accept : null;
|
||||
},
|
||||
rejectLabel() {
|
||||
return this.confirmation ? (this.confirmation.rejectLabel || this.$primevue.config.locale.reject) : null;
|
||||
return this.confirmation ? this.confirmation.rejectLabel || this.$primevue.config.locale.reject : null;
|
||||
},
|
||||
acceptIcon() {
|
||||
return this.confirmation ? this.confirmation.acceptIcon : null;
|
||||
|
@ -106,10 +113,10 @@ export default {
|
|||
return ['p-confirm-dialog-accept', this.confirmation ? this.confirmation.acceptClass : null];
|
||||
},
|
||||
rejectClass() {
|
||||
return ['p-confirm-dialog-reject', this.confirmation ? (this.confirmation.rejectClass || 'p-button-text') : null];
|
||||
return ['p-confirm-dialog-reject', this.confirmation ? this.confirmation.rejectClass || 'p-button-text' : null];
|
||||
},
|
||||
autoFocusAccept() {
|
||||
return (this.confirmation.defaultFocus === undefined || this.confirmation.defaultFocus === 'accept') ? true : false;
|
||||
return this.confirmation.defaultFocus === undefined || this.confirmation.defaultFocus === 'accept' ? true : false;
|
||||
},
|
||||
autoFocusReject() {
|
||||
return this.confirmation.defaultFocus === 'reject' ? true : false;
|
||||
|
@ -119,8 +126,8 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
'CDialog': Dialog,
|
||||
'CDButton': Button
|
||||
CDialog: Dialog,
|
||||
CDButton: Button
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -14,19 +14,16 @@ export interface ConfirmPopupSlots {
|
|||
* Custom message template.
|
||||
* @param {Object} scope - message slot's params.
|
||||
*/
|
||||
message: (scope: {
|
||||
message: ConfirmationOptions;
|
||||
}) => VNode[];
|
||||
message: (scope: { message: ConfirmationOptions }) => VNode[];
|
||||
}
|
||||
|
||||
export declare type ConfirmPopupEmits = {
|
||||
}
|
||||
export declare type ConfirmPopupEmits = {};
|
||||
|
||||
declare class ConfirmPopup extends ClassComponent<ConfirmPopupProps, ConfirmPopupSlots, ConfirmPopupEmits> { }
|
||||
declare class ConfirmPopup extends ClassComponent<ConfirmPopupProps, ConfirmPopupSlots, ConfirmPopupEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
ConfirmPopup: GlobalComponentConstructor<ConfirmPopup>
|
||||
ConfirmPopup: GlobalComponentConstructor<ConfirmPopup>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +38,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [ConfirmPopup](https://www.primefaces.org/primevue/showcase/#/confirmpopup)
|
||||
* - [ConfirmPopup](https://www.primefaces.org/primevue/confirmpopup)
|
||||
*
|
||||
*/
|
||||
export default ConfirmPopup;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<Portal>
|
||||
<transition name="p-confirm-popup" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
|
||||
<div :class="containerClass" v-if="visible" :ref="containerRef" v-bind="$attrs" @click="onOverlayClick">
|
||||
<div v-if="visible" :ref="containerRef" :class="containerClass" v-bind="$attrs" @click="onOverlayClick">
|
||||
<template v-if="!$slots.message">
|
||||
<div class="p-confirm-popup-content">
|
||||
<i :class="iconClass" />
|
||||
<span class="p-confirm-popup-message">{{confirmation.message}}</span>
|
||||
<span class="p-confirm-popup-message">{{ confirmation.message }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<component v-else :is="$slots.message" :message="confirmation"></component>
|
||||
<div class="p-confirm-popup-footer">
|
||||
<CPButton :label="rejectLabel" :icon="rejectIcon" :class="rejectClass" @click="reject()"/>
|
||||
<CPButton :label="rejectLabel" :icon="rejectIcon" :class="rejectClass" @click="reject()" />
|
||||
<CPButton :label="acceptLabel" :icon="acceptIcon" :class="acceptClass" @click="accept()" autofocus />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -20,7 +20,7 @@
|
|||
|
||||
<script>
|
||||
import ConfirmationEventBus from 'primevue/confirmationeventbus';
|
||||
import {ConnectedOverlayScrollHandler,DomHandler,ZIndexUtils} from 'primevue/utils';
|
||||
import { ConnectedOverlayScrollHandler, DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import Button from 'primevue/button';
|
||||
import Portal from 'primevue/portal';
|
||||
|
@ -35,7 +35,7 @@ export default {
|
|||
return {
|
||||
visible: false,
|
||||
confirmation: null
|
||||
}
|
||||
};
|
||||
},
|
||||
target: null,
|
||||
outsideClickListener: null,
|
||||
|
@ -56,10 +56,12 @@ export default {
|
|||
this.visible = true;
|
||||
}
|
||||
};
|
||||
|
||||
this.closeListener = () => {
|
||||
this.visible = false;
|
||||
this.confirmation = null;
|
||||
};
|
||||
|
||||
ConfirmationEventBus.on('confirm', this.confirmListener);
|
||||
ConfirmationEventBus.on('close', this.closeListener);
|
||||
},
|
||||
|
@ -68,10 +70,12 @@ export default {
|
|||
ConfirmationEventBus.off('close', this.closeListener);
|
||||
|
||||
this.unbindOutsideClickListener();
|
||||
|
||||
if (this.scrollHandler) {
|
||||
this.scrollHandler.destroy();
|
||||
this.scrollHandler = null;
|
||||
}
|
||||
|
||||
this.unbindResizeListener();
|
||||
|
||||
if (this.container) {
|
||||
|
@ -83,7 +87,7 @@ export default {
|
|||
this.confirmation = null;
|
||||
},
|
||||
methods: {
|
||||
accept() {
|
||||
accept() {
|
||||
if (this.confirmation.accept) {
|
||||
this.confirmation.accept();
|
||||
}
|
||||
|
@ -122,6 +126,7 @@ export default {
|
|||
if (containerOffset.left < targetOffset.left) {
|
||||
arrowLeft = targetOffset.left - containerOffset.left;
|
||||
}
|
||||
|
||||
this.container.style.setProperty('--overlayArrowLeft', `${arrowLeft}px`);
|
||||
|
||||
if (containerOffset.top < targetOffset.top) {
|
||||
|
@ -137,6 +142,7 @@ export default {
|
|||
this.alignOverlay();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
|
@ -169,6 +175,7 @@ export default {
|
|||
this.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', this.resizeListener);
|
||||
}
|
||||
},
|
||||
|
@ -193,10 +200,13 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-confirm-popup p-component', {
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}];
|
||||
return [
|
||||
'p-confirm-popup p-component',
|
||||
{
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
},
|
||||
message() {
|
||||
return this.confirmation ? this.confirmation.message : null;
|
||||
|
@ -205,10 +215,10 @@ export default {
|
|||
return ['p-confirm-popup-icon', this.confirmation ? this.confirmation.icon : null];
|
||||
},
|
||||
acceptLabel() {
|
||||
return this.confirmation ? (this.confirmation.acceptLabel || this.$primevue.config.locale.accept) : null;
|
||||
return this.confirmation ? this.confirmation.acceptLabel || this.$primevue.config.locale.accept : null;
|
||||
},
|
||||
rejectLabel() {
|
||||
return this.confirmation ? (this.confirmation.rejectLabel || this.$primevue.config.locale.reject) : null;
|
||||
return this.confirmation ? this.confirmation.rejectLabel || this.$primevue.config.locale.reject : null;
|
||||
},
|
||||
acceptIcon() {
|
||||
return this.confirmation ? this.confirmation.acceptIcon : null;
|
||||
|
@ -220,14 +230,14 @@ export default {
|
|||
return ['p-confirm-popup-accept p-button-sm', this.confirmation ? this.confirmation.acceptClass : null];
|
||||
},
|
||||
rejectClass() {
|
||||
return ['p-confirm-popup-reject p-button-sm', this.confirmation ? (this.confirmation.rejectClass || 'p-button-text') : null];
|
||||
return ['p-confirm-popup-reject p-button-sm', this.confirmation ? this.confirmation.rejectClass || 'p-button-text' : null];
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'CPButton': Button,
|
||||
'Portal': Portal
|
||||
CPButton: Button,
|
||||
Portal: Portal
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -254,34 +264,36 @@ export default {
|
|||
}
|
||||
|
||||
.p-confirm-popup-enter-active {
|
||||
transition: transform .12s cubic-bezier(0, 0, 0.2, 1), opacity .12s cubic-bezier(0, 0, 0.2, 1);
|
||||
transition: transform 0.12s cubic-bezier(0, 0, 0.2, 1), opacity 0.12s cubic-bezier(0, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.p-confirm-popup-leave-active {
|
||||
transition: opacity .1s linear;
|
||||
transition: opacity 0.1s linear;
|
||||
}
|
||||
|
||||
.p-confirm-popup:after, .p-confirm-popup:before {
|
||||
bottom: 100%;
|
||||
left: calc(var(--overlayArrowLeft, 0) + 1.25rem);
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
.p-confirm-popup:after,
|
||||
.p-confirm-popup:before {
|
||||
bottom: 100%;
|
||||
left: calc(var(--overlayArrowLeft, 0) + 1.25rem);
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-confirm-popup:after {
|
||||
border-width: 8px;
|
||||
margin-left: -8px;
|
||||
border-width: 8px;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.p-confirm-popup:before {
|
||||
border-width: 10px;
|
||||
margin-left: -10px;
|
||||
border-width: 10px;
|
||||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.p-confirm-popup-flipped:after, .p-confirm-popup-flipped:before {
|
||||
.p-confirm-popup-flipped:after,
|
||||
.p-confirm-popup-flipped:before {
|
||||
bottom: auto;
|
||||
top: 100%;
|
||||
}
|
||||
|
@ -291,7 +303,7 @@ export default {
|
|||
}
|
||||
|
||||
.p-confirm-popup.p-confirm-popup-flipped:before {
|
||||
border-bottom-color: transparent
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.p-confirm-popup .p-confirm-popup-content {
|
||||
|
|
|
@ -49,8 +49,7 @@ export interface ContextMenuSlots {
|
|||
}) => VNode[];
|
||||
}
|
||||
|
||||
export declare type ContextMenuEmits = {
|
||||
}
|
||||
export declare type ContextMenuEmits = {};
|
||||
|
||||
declare class ContextMenu extends ClassComponent<ContextMenuProps, ContextMenuSlots, ContextMenuEmits> {
|
||||
/**
|
||||
|
@ -77,7 +76,7 @@ declare class ContextMenu extends ClassComponent<ContextMenuProps, ContextMenuSl
|
|||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
ContextMenu: GlobalComponentConstructor<ContextMenu>
|
||||
ContextMenu: GlobalComponentConstructor<ContextMenu>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,11 +87,11 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Helper API:
|
||||
*
|
||||
* - [MenuItem](https://www.primefaces.org/primevue/showcase/#/menumodel)
|
||||
* - [MenuItem](https://www.primefaces.org/primevue/menumodel)
|
||||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [ContextMenu](https://www.primefaces.org/primevue/showcase/#/contextmenu)
|
||||
* - [ContextMenu](https://www.primefaces.org/primevue/contextmenu)
|
||||
*
|
||||
*/
|
||||
export default ContextMenu;
|
||||
|
|
|
@ -17,139 +17,136 @@ describe('ContextMenu.vue', () => {
|
|||
props: {
|
||||
model: [
|
||||
{
|
||||
label:'File',
|
||||
icon:'pi pi-fw pi-file',
|
||||
items:[
|
||||
label: 'File',
|
||||
icon: 'pi pi-fw pi-file',
|
||||
items: [
|
||||
{
|
||||
label:'New',
|
||||
icon:'pi pi-fw pi-plus',
|
||||
items:[
|
||||
label: 'New',
|
||||
icon: 'pi pi-fw pi-plus',
|
||||
items: [
|
||||
{
|
||||
label:'Bookmark',
|
||||
icon:'pi pi-fw pi-bookmark'
|
||||
label: 'Bookmark',
|
||||
icon: 'pi pi-fw pi-bookmark'
|
||||
},
|
||||
{
|
||||
label:'Video',
|
||||
icon:'pi pi-fw pi-video'
|
||||
},
|
||||
]
|
||||
label: 'Video',
|
||||
icon: 'pi pi-fw pi-video'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'Delete',
|
||||
icon:'pi pi-fw pi-trash'
|
||||
label: 'Delete',
|
||||
icon: 'pi pi-fw pi-trash'
|
||||
},
|
||||
{
|
||||
separator:true
|
||||
separator: true
|
||||
},
|
||||
{
|
||||
label:'Export',
|
||||
icon:'pi pi-fw pi-external-link'
|
||||
label: 'Export',
|
||||
icon: 'pi pi-fw pi-external-link'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'Edit',
|
||||
icon:'pi pi-fw pi-pencil',
|
||||
items:[
|
||||
label: 'Edit',
|
||||
icon: 'pi pi-fw pi-pencil',
|
||||
items: [
|
||||
{
|
||||
label:'Left',
|
||||
icon:'pi pi-fw pi-align-left'
|
||||
label: 'Left',
|
||||
icon: 'pi pi-fw pi-align-left'
|
||||
},
|
||||
{
|
||||
label:'Right',
|
||||
icon:'pi pi-fw pi-align-right'
|
||||
label: 'Right',
|
||||
icon: 'pi pi-fw pi-align-right'
|
||||
},
|
||||
{
|
||||
label:'Center',
|
||||
icon:'pi pi-fw pi-align-center'
|
||||
label: 'Center',
|
||||
icon: 'pi pi-fw pi-align-center'
|
||||
},
|
||||
{
|
||||
label:'Justify',
|
||||
icon:'pi pi-fw pi-align-justify'
|
||||
},
|
||||
|
||||
label: 'Justify',
|
||||
icon: 'pi pi-fw pi-align-justify'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'Users',
|
||||
icon:'pi pi-fw pi-user',
|
||||
items:[
|
||||
label: 'Users',
|
||||
icon: 'pi pi-fw pi-user',
|
||||
items: [
|
||||
{
|
||||
label:'New',
|
||||
icon:'pi pi-fw pi-user-plus',
|
||||
|
||||
label: 'New',
|
||||
icon: 'pi pi-fw pi-user-plus'
|
||||
},
|
||||
{
|
||||
label:'Delete',
|
||||
icon:'pi pi-fw pi-user-minus',
|
||||
|
||||
label: 'Delete',
|
||||
icon: 'pi pi-fw pi-user-minus'
|
||||
},
|
||||
{
|
||||
label:'Search',
|
||||
icon:'pi pi-fw pi-users',
|
||||
items:[
|
||||
label: 'Search',
|
||||
icon: 'pi pi-fw pi-users',
|
||||
items: [
|
||||
{
|
||||
label:'Filter',
|
||||
icon:'pi pi-fw pi-filter',
|
||||
items:[
|
||||
label: 'Filter',
|
||||
icon: 'pi pi-fw pi-filter',
|
||||
items: [
|
||||
{
|
||||
label:'Print',
|
||||
icon:'pi pi-fw pi-print'
|
||||
label: 'Print',
|
||||
icon: 'pi pi-fw pi-print'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
icon:'pi pi-fw pi-bars',
|
||||
label:'List'
|
||||
icon: 'pi pi-fw pi-bars',
|
||||
label: 'List'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'Events',
|
||||
icon:'pi pi-fw pi-calendar',
|
||||
items:[
|
||||
label: 'Events',
|
||||
icon: 'pi pi-fw pi-calendar',
|
||||
items: [
|
||||
{
|
||||
label:'Edit',
|
||||
icon:'pi pi-fw pi-pencil',
|
||||
items:[
|
||||
label: 'Edit',
|
||||
icon: 'pi pi-fw pi-pencil',
|
||||
items: [
|
||||
{
|
||||
label:'Save',
|
||||
icon:'pi pi-fw pi-calendar-plus'
|
||||
label: 'Save',
|
||||
icon: 'pi pi-fw pi-calendar-plus'
|
||||
},
|
||||
{
|
||||
label:'Delete',
|
||||
icon:'pi pi-fw pi-calendar-minus'
|
||||
},
|
||||
label: 'Delete',
|
||||
icon: 'pi pi-fw pi-calendar-minus'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'Archieve',
|
||||
icon:'pi pi-fw pi-calendar-times',
|
||||
items:[
|
||||
label: 'Archieve',
|
||||
icon: 'pi pi-fw pi-calendar-times',
|
||||
items: [
|
||||
{
|
||||
label:'Remove',
|
||||
icon:'pi pi-fw pi-calendar-minus'
|
||||
label: 'Remove',
|
||||
icon: 'pi pi-fw pi-calendar-minus'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
separator:true
|
||||
separator: true
|
||||
},
|
||||
{
|
||||
label:'Quit',
|
||||
icon:'pi pi-fw pi-power-off'
|
||||
label: 'Quit',
|
||||
icon: 'pi pi-fw pi-power-off'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should exist', async() => {
|
||||
const event = { pageX: 100, pageY: 120, preventDefault: () => {}, stopPropagation: () => {}};
|
||||
it('should exist', async () => {
|
||||
const event = { pageX: 100, pageY: 120, preventDefault: () => {}, stopPropagation: () => {} };
|
||||
const show = jest.spyOn(wrapper.vm, 'show');
|
||||
|
||||
wrapper.vm.show(event);
|
||||
|
@ -161,7 +158,7 @@ describe('ContextMenu.vue', () => {
|
|||
expect(wrapper.findAll('.p-menuitem-text')[0].text()).toBe('File');
|
||||
});
|
||||
|
||||
it('should hide menu', async() => {
|
||||
it('should hide menu', async () => {
|
||||
const hide = jest.spyOn(wrapper.vm, 'hide');
|
||||
|
||||
await wrapper.setData({ visible: true });
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<Portal :appendTo="appendTo">
|
||||
<transition name="p-contextmenu" @enter="onEnter" @leave="onLeave" @after-leave="onAfterLeave">
|
||||
<div :ref="containerRef" :class="containerClass" v-if="visible" v-bind="$attrs">
|
||||
<div v-if="visible" :ref="containerRef" :class="containerClass" v-bind="$attrs">
|
||||
<ContextMenuSub :model="model" :root="true" @leaf-click="onLeafClick" :template="$slots.item" :exact="exact" />
|
||||
</div>
|
||||
</transition>
|
||||
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler,ZIndexUtils} from 'primevue/utils';
|
||||
import { DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
import ContextMenuSub from './ContextMenuSub.vue';
|
||||
import Portal from 'primevue/portal';
|
||||
|
||||
|
@ -17,7 +17,7 @@ export default {
|
|||
name: 'ContextMenu',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
model: {
|
||||
model: {
|
||||
type: Array,
|
||||
default: null
|
||||
},
|
||||
|
@ -62,6 +62,7 @@ export default {
|
|||
if (this.container && this.autoZIndex) {
|
||||
ZIndexUtils.clear(this.container);
|
||||
}
|
||||
|
||||
this.container = null;
|
||||
},
|
||||
mounted() {
|
||||
|
@ -72,17 +73,17 @@ export default {
|
|||
methods: {
|
||||
itemClick(event) {
|
||||
const item = event.item;
|
||||
|
||||
if (item.command) {
|
||||
item.command(event);
|
||||
event.originalEvent.preventDefault();
|
||||
}
|
||||
|
||||
this.hide();
|
||||
},
|
||||
toggle(event) {
|
||||
if (this.visible)
|
||||
this.hide();
|
||||
else
|
||||
this.show(event);
|
||||
if (this.visible) this.hide();
|
||||
else this.show(event);
|
||||
},
|
||||
onLeafClick() {
|
||||
this.hide();
|
||||
|
@ -91,10 +92,8 @@ export default {
|
|||
this.pageX = event.pageX;
|
||||
this.pageY = event.pageY;
|
||||
|
||||
if (this.visible)
|
||||
this.position();
|
||||
else
|
||||
this.visible = true;
|
||||
if (this.visible) this.position();
|
||||
else this.visible = true;
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
@ -157,6 +156,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
|
@ -173,6 +173,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', this.resizeListener);
|
||||
}
|
||||
},
|
||||
|
@ -192,7 +193,7 @@ export default {
|
|||
}
|
||||
},
|
||||
unbindDocumentContextMenuListener() {
|
||||
if(this.documentContextMenuListener) {
|
||||
if (this.documentContextMenuListener) {
|
||||
document.removeEventListener('contextmenu', this.documentContextMenuListener);
|
||||
this.documentContextMenuListener = null;
|
||||
}
|
||||
|
@ -203,17 +204,20 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-contextmenu p-component', {
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}]
|
||||
return [
|
||||
'p-contextmenu p-component',
|
||||
{
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'ContextMenuSub': ContextMenuSub,
|
||||
'Portal': Portal
|
||||
ContextMenuSub: ContextMenuSub,
|
||||
Portal: Portal
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,35 +1,43 @@
|
|||
<template>
|
||||
<transition name="p-contextmenusub" @enter="onEnter">
|
||||
<ul ref="container" :class="containerClass" role="menu" v-if="root ? true : parentActive">
|
||||
<ul v-if="root ? true : parentActive" ref="container" :class="containerClass" role="menu">
|
||||
<template v-for="(item, i) of model" :key="label(item) + i.toString()">
|
||||
<li role="none" :class="getItemClass(item)" :style="item.style" v-if="visible(item) && !item.separator"
|
||||
@mouseenter="onItemMouseEnter($event, item)">
|
||||
<li v-if="visible(item) && !item.separator" role="none" :class="getItemClass(item)" :style="item.style" @mouseenter="onItemMouseEnter($event, item)">
|
||||
<template v-if="!template">
|
||||
<router-link v-if="item.to && !disabled(item)" :to="item.to" custom v-slot="{navigate, href, isActive, isExactActive}">
|
||||
<a :href="href" @click="onItemClick($event, item, navigate)" :class="linkClass(item, {isActive, isExactActive})" v-ripple role="menuitem">
|
||||
<span :class="['p-menuitem-icon', item.icon]" v-if="item.icon"></span>
|
||||
<span class="p-menuitem-text">{{label(item)}}</span>
|
||||
<router-link v-if="item.to && !disabled(item)" v-slot="{ navigate, href, isActive, isExactActive }" :to="item.to" custom>
|
||||
<a v-ripple :href="href" @click="onItemClick($event, item, navigate)" :class="linkClass(item, { isActive, isExactActive })" role="menuitem">
|
||||
<span v-if="item.icon" :class="['p-menuitem-icon', item.icon]"></span>
|
||||
<span class="p-menuitem-text">{{ label(item) }}</span>
|
||||
</a>
|
||||
</router-link>
|
||||
<a v-else :href="item.url" :class="linkClass(item)" :target="item.target" @click="onItemClick($event, item)" v-ripple
|
||||
:aria-haspopup="item.items != null" :aria-expanded="item === activeItem" role="menuitem" :tabindex="disabled(item) ? null : '0'">
|
||||
<span :class="['p-menuitem-icon', item.icon]" v-if="item.icon"></span>
|
||||
<span class="p-menuitem-text">{{label(item)}}</span>
|
||||
<span class="p-submenu-icon pi pi-angle-right" v-if="item.items"></span>
|
||||
<a
|
||||
v-else
|
||||
v-ripple
|
||||
:href="item.url"
|
||||
:class="linkClass(item)"
|
||||
:target="item.target"
|
||||
@click="onItemClick($event, item)"
|
||||
:aria-haspopup="item.items != null"
|
||||
:aria-expanded="item === activeItem"
|
||||
role="menuitem"
|
||||
:tabindex="disabled(item) ? null : '0'"
|
||||
>
|
||||
<span v-if="item.icon" :class="['p-menuitem-icon', item.icon]"></span>
|
||||
<span class="p-menuitem-text">{{ label(item) }}</span>
|
||||
<span v-if="item.items" class="p-submenu-icon pi pi-angle-right"></span>
|
||||
</a>
|
||||
</template>
|
||||
<component v-else :is="template" :item="item"></component>
|
||||
<ContextMenuSub :model="item.items" v-if="visible(item) && item.items" :key="label(item) + '_sub_'" :template="template"
|
||||
@leaf-click="onLeafClick" :parentActive="item === activeItem" :exact="exact" />
|
||||
<ContextMenuSub v-if="visible(item) && item.items" :key="label(item) + '_sub_'" :model="item.items" :template="template" @leaf-click="onLeafClick" :parentActive="item === activeItem" :exact="exact" />
|
||||
</li>
|
||||
<li :class="['p-menu-separator', item.class]" :style="item.style" v-if="visible(item) && item.separator" :key="'separator' + i.toString()" role="separator"></li>
|
||||
<li v-if="visible(item) && item.separator" :key="'separator' + i.toString()" :class="['p-menu-separator', item.class]" :style="item.style" role="separator"></li>
|
||||
</template>
|
||||
</ul>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler} from 'primevue/utils';
|
||||
import { DomHandler } from 'primevue/utils';
|
||||
import Ripple from 'primevue/ripple';
|
||||
|
||||
export default {
|
||||
|
@ -57,6 +65,11 @@ export default {
|
|||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItem: null
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
parentActive(newValue) {
|
||||
if (!newValue) {
|
||||
|
@ -64,15 +77,11 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItem: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onItemMouseEnter(event, item) {
|
||||
if (this.disabled(item)) {
|
||||
event.preventDefault();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -81,6 +90,7 @@ export default {
|
|||
onItemClick(event, item, navigate) {
|
||||
if (this.disabled(item)) {
|
||||
event.preventDefault();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,10 +102,8 @@ export default {
|
|||
}
|
||||
|
||||
if (item.items) {
|
||||
if (this.activeItem && item === this.activeItem)
|
||||
this.activeItem = null;
|
||||
else
|
||||
this.activeItem = item;
|
||||
if (this.activeItem && item === this.activeItem) this.activeItem = null;
|
||||
else this.activeItem = item;
|
||||
}
|
||||
|
||||
if (!item.items) {
|
||||
|
@ -115,51 +123,55 @@ export default {
|
|||
},
|
||||
position() {
|
||||
const parentItem = this.$refs.container.parentElement;
|
||||
const containerOffset = DomHandler.getOffset(this.$refs.container.parentElement)
|
||||
const containerOffset = DomHandler.getOffset(this.$refs.container.parentElement);
|
||||
const viewport = DomHandler.getViewport();
|
||||
const sublistWidth = this.$refs.container.offsetParent ? this.$refs.container.offsetWidth : DomHandler.getHiddenElementOuterWidth(this.$refs.container);
|
||||
const itemOuterWidth = DomHandler.getOuterWidth(parentItem.children[0]);
|
||||
|
||||
this.$refs.container.style.top = '0px';
|
||||
|
||||
if ((parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth) > (viewport.width - DomHandler.calculateScrollbarWidth())) {
|
||||
if (parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth > viewport.width - DomHandler.calculateScrollbarWidth()) {
|
||||
this.$refs.container.style.left = -1 * sublistWidth + 'px';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.$refs.container.style.left = itemOuterWidth + 'px';
|
||||
}
|
||||
},
|
||||
getItemClass(item) {
|
||||
return [
|
||||
'p-menuitem', item.class, {
|
||||
'p-menuitem',
|
||||
item.class,
|
||||
{
|
||||
'p-menuitem-active': this.activeItem === item
|
||||
}
|
||||
]
|
||||
];
|
||||
},
|
||||
linkClass(item, routerProps) {
|
||||
return ['p-menuitem-link', {
|
||||
'p-disabled': this.disabled(item),
|
||||
'router-link-active': routerProps && routerProps.isActive,
|
||||
'router-link-active-exact': this.exact && routerProps && routerProps.isExactActive
|
||||
}];
|
||||
return [
|
||||
'p-menuitem-link',
|
||||
{
|
||||
'p-disabled': this.disabled(item),
|
||||
'router-link-active': routerProps && routerProps.isActive,
|
||||
'router-link-active-exact': this.exact && routerProps && routerProps.isExactActive
|
||||
}
|
||||
];
|
||||
},
|
||||
visible(item) {
|
||||
return (typeof item.visible === 'function' ? item.visible() : item.visible !== false);
|
||||
return typeof item.visible === 'function' ? item.visible() : item.visible !== false;
|
||||
},
|
||||
disabled(item) {
|
||||
return (typeof item.disabled === 'function' ? item.disabled() : item.disabled);
|
||||
return typeof item.disabled === 'function' ? item.disabled() : item.disabled;
|
||||
},
|
||||
label(item) {
|
||||
return (typeof item.label === 'function' ? item.label() : item.label);
|
||||
return typeof item.label === 'function' ? item.label() : item.label;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return {'p-submenu-list': !this.root};
|
||||
return { 'p-submenu-list': !this.root };
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
ripple: Ripple
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,41 +1,51 @@
|
|||
<template>
|
||||
<td v-if="loading" :style="containerStyle" :class="containerClass">
|
||||
<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 v-else :style="containerStyle" :class="containerClass" @click="onClick" @keydown="onKeyDown" role="cell">
|
||||
<span v-if="responsiveLayout === 'stack'" class="p-column-title">{{columnProp('header')}}</span>
|
||||
<component :is="column.children.body" :data="rowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" :editorInitCallback="editorInitCallback" v-if="column.children && column.children.body && !d_editing" />
|
||||
<component :is="column.children.editor" :data="editingRowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" :editorSaveCallback="editorSaveCallback" :editorCancelCallback="editorCancelCallback" v-else-if="column.children && column.children.editor && d_editing" />
|
||||
<component :is="column.children.body" :data="editingRowData" :column="column" :field="field" :index="rowIndex" :frozenRow="frozenRow" v-else-if="column.children && column.children.body && !column.children.editor && d_editing" />
|
||||
<span v-if="responsiveLayout === 'stack'" class="p-column-title">{{ 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-else-if="column.children && column.children.editor && d_editing"
|
||||
:is="column.children.editor"
|
||||
:data="editingRowData"
|
||||
:column="column"
|
||||
:field="field"
|
||||
:index="rowIndex"
|
||||
:frozenRow="frozenRow"
|
||||
:editorSaveCallback="editorSaveCallback"
|
||||
:editorCancelCallback="editorCancelCallback"
|
||||
/>
|
||||
<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')">
|
||||
<DTRadioButton :value="rowData" :checked="selected" @change="toggleRowWithRadio($event, rowIndex)" v-if="columnProp('selectionMode') === 'single'" />
|
||||
<DTCheckbox :value="rowData" :checked="selected" @change="toggleRowWithCheckbox($event, rowIndex)" v-else-if="columnProp('selectionMode') ==='multiple'" />
|
||||
<DTRadioButton v-if="columnProp('selectionMode') === 'single'" :value="rowData" :checked="selected" @change="toggleRowWithRadio($event, rowIndex)" />
|
||||
<DTCheckbox v-else-if="columnProp('selectionMode') === 'multiple'" :value="rowData" :checked="selected" @change="toggleRowWithCheckbox($event, rowIndex)" />
|
||||
</template>
|
||||
<template v-else-if="columnProp('rowReorder')">
|
||||
<i :class="['p-datatable-reorderablerow-handle', (columnProp('rowReorderIcon') || 'pi pi-bars')]"></i>
|
||||
<i :class="['p-datatable-reorderablerow-handle', columnProp('rowReorderIcon') || 'pi pi-bars']"></i>
|
||||
</template>
|
||||
<template v-else-if="columnProp('expander')">
|
||||
<button class="p-row-toggler p-link" @click="toggleRow" type="button" v-ripple>
|
||||
<button v-ripple class="p-row-toggler p-link" @click="toggleRow" type="button">
|
||||
<span :class="rowTogglerIcon"></span>
|
||||
</button>
|
||||
</template>
|
||||
<template v-else-if="editMode === 'row' && columnProp('rowEditor')">
|
||||
<button class="p-row-editor-init p-link" v-if="!d_editing" @click="onRowEditInit" type="button" v-ripple>
|
||||
<button v-if="!d_editing" v-ripple class="p-row-editor-init p-link" @click="onRowEditInit" type="button">
|
||||
<span class="p-row-editor-init-icon pi pi-fw pi-pencil"></span>
|
||||
</button>
|
||||
<button class="p-row-editor-save p-link" v-if="d_editing" @click="onRowEditSave" type="button" v-ripple>
|
||||
<button v-if="d_editing" v-ripple class="p-row-editor-save p-link" @click="onRowEditSave" type="button">
|
||||
<span class="p-row-editor-save-icon pi pi-fw pi-check"></span>
|
||||
</button>
|
||||
<button class="p-row-editor-cancel p-link" v-if="d_editing" @click="onRowEditCancel" type="button" v-ripple>
|
||||
<button v-if="d_editing" v-ripple class="p-row-editor-cancel p-link" @click="onRowEditCancel" type="button">
|
||||
<span class="p-row-editor-cancel-icon pi pi-fw pi-times"></span>
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>{{resolveFieldData()}}</template>
|
||||
<template v-else>{{ resolveFieldData() }}</template>
|
||||
</td>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler,ObjectUtils} from 'primevue/utils';
|
||||
import { DomHandler, ObjectUtils } from 'primevue/utils';
|
||||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import RowRadioButton from './RowRadioButton.vue';
|
||||
import RowCheckbox from './RowCheckbox.vue';
|
||||
|
@ -43,8 +53,7 @@ import Ripple from 'primevue/ripple';
|
|||
|
||||
export default {
|
||||
name: 'BodyCell',
|
||||
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: {
|
||||
rowData: {
|
||||
type: Object,
|
||||
|
@ -102,14 +111,14 @@ export default {
|
|||
return {
|
||||
d_editing: this.editing,
|
||||
styleObject: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
editing(newValue) {
|
||||
this.d_editing = newValue;
|
||||
},
|
||||
'$data.d_editing': function(newValue) {
|
||||
this.$emit('editing-meta-change', {data: this.rowData, field: (this.field || `field_${this.index}`), index: this.rowIndex, editing: newValue});
|
||||
'$data.d_editing': function (newValue) {
|
||||
this.$emit('editing-meta-change', { data: this.rowData, field: this.field || `field_${this.index}`, index: this.rowIndex, editing: newValue });
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -124,6 +133,7 @@ export default {
|
|||
|
||||
if (this.d_editing && (this.editMode === 'cell' || (this.editMode === 'row' && this.columnProp('rowEditor')))) {
|
||||
const focusableEl = DomHandler.getFirstFocusableElement(this.$el);
|
||||
|
||||
focusableEl && focusableEl.focus();
|
||||
}
|
||||
},
|
||||
|
@ -147,7 +157,7 @@ export default {
|
|||
});
|
||||
},
|
||||
toggleRowWithRadio(event, index) {
|
||||
this.$emit('radio-change', { originalEvent: event.originalEvent, index: index, data: event.data});
|
||||
this.$emit('radio-change', { originalEvent: event.originalEvent, index: index, data: event.data });
|
||||
},
|
||||
toggleRowWithCheckbox(event, index) {
|
||||
this.$emit('checkbox-change', { originalEvent: event.originalEvent, index: index, data: event.data });
|
||||
|
@ -161,6 +171,7 @@ export default {
|
|||
if (!this.selfClick) {
|
||||
this.completeEdit(event, 'outside');
|
||||
}
|
||||
|
||||
this.selfClick = false;
|
||||
};
|
||||
|
||||
|
@ -187,13 +198,14 @@ export default {
|
|||
if (!this.d_editing) {
|
||||
this.d_editing = true;
|
||||
this.bindDocumentEditListener();
|
||||
this.$emit('cell-edit-init', {originalEvent: event, data: this.rowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('cell-edit-init', { originalEvent: event, data: this.rowData, field: this.field, index: this.rowIndex });
|
||||
|
||||
this.overlayEventListener = (e) => {
|
||||
if (this.$el && this.$el.contains(e.target)) {
|
||||
this.selfClick = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OverlayEventBus.on('overlay-click', this.overlayEventListener);
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +221,7 @@ export default {
|
|||
index: this.rowIndex,
|
||||
type: type,
|
||||
defaultPrevented: false,
|
||||
preventDefault: function() {
|
||||
preventDefault: function () {
|
||||
this.defaultPrevented = true;
|
||||
}
|
||||
};
|
||||
|
@ -225,21 +237,19 @@ export default {
|
|||
switch (event.which) {
|
||||
case 13:
|
||||
this.completeEdit(event, 'enter');
|
||||
break;
|
||||
break;
|
||||
|
||||
case 27:
|
||||
this.switchCellToViewMode();
|
||||
this.$emit('cell-edit-cancel', {originalEvent: event, data: this.rowData, field: this.field, index: this.rowIndex});
|
||||
break;
|
||||
this.$emit('cell-edit-cancel', { originalEvent: event, data: this.rowData, field: this.field, index: this.rowIndex });
|
||||
break;
|
||||
|
||||
case 9:
|
||||
this.completeEdit(event, 'tab');
|
||||
|
||||
if (event.shiftKey)
|
||||
this.moveToPreviousCell(event);
|
||||
else
|
||||
this.moveToNextCell(event);
|
||||
break;
|
||||
if (event.shiftKey) this.moveToPreviousCell(event);
|
||||
else this.moveToNextCell(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -264,13 +274,13 @@ export default {
|
|||
findCell(element) {
|
||||
if (element) {
|
||||
let cell = element;
|
||||
|
||||
while (cell && !DomHandler.hasClass(cell, 'p-cell-editing')) {
|
||||
cell = cell.parentElement;
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
@ -279,18 +289,16 @@ export default {
|
|||
|
||||
if (!prevCell) {
|
||||
let previousRow = cell.parentElement.previousElementSibling;
|
||||
|
||||
if (previousRow) {
|
||||
prevCell = previousRow.lastElementChild;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevCell) {
|
||||
if (DomHandler.hasClass(prevCell, 'p-editable-column'))
|
||||
return prevCell;
|
||||
else
|
||||
return this.findPreviousEditableColumn(prevCell);
|
||||
}
|
||||
else {
|
||||
if (DomHandler.hasClass(prevCell, 'p-editable-column')) return prevCell;
|
||||
else return this.findPreviousEditableColumn(prevCell);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
@ -299,68 +307,70 @@ export default {
|
|||
|
||||
if (!nextCell) {
|
||||
let nextRow = cell.parentElement.nextElementSibling;
|
||||
|
||||
if (nextRow) {
|
||||
nextCell = nextRow.firstElementChild;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextCell) {
|
||||
if (DomHandler.hasClass(nextCell, 'p-editable-column'))
|
||||
return nextCell;
|
||||
else
|
||||
return this.findNextEditableColumn(nextCell);
|
||||
}
|
||||
else {
|
||||
if (DomHandler.hasClass(nextCell, 'p-editable-column')) return nextCell;
|
||||
else return this.findNextEditableColumn(nextCell);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
isEditingCellValid() {
|
||||
return (DomHandler.find(this.$el, '.p-invalid').length === 0);
|
||||
return DomHandler.find(this.$el, '.p-invalid').length === 0;
|
||||
},
|
||||
onRowEditInit(event) {
|
||||
this.$emit('row-edit-init', {originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('row-edit-init', { originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex });
|
||||
},
|
||||
onRowEditSave(event) {
|
||||
this.$emit('row-edit-save', {originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('row-edit-save', { originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex });
|
||||
},
|
||||
onRowEditCancel(event) {
|
||||
this.$emit('row-edit-cancel', {originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('row-edit-cancel', { originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex });
|
||||
},
|
||||
editorInitCallback(event) {
|
||||
this.$emit('row-edit-init', {originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('row-edit-init', { originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex });
|
||||
},
|
||||
editorSaveCallback(event) {
|
||||
if (this.editMode === 'row') {
|
||||
this.$emit('row-edit-save', {originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('row-edit-save', { originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex });
|
||||
} else {
|
||||
this.completeEdit(event, 'enter');
|
||||
}
|
||||
},
|
||||
editorCancelCallback(event) {
|
||||
if (this.editMode === 'row') {
|
||||
this.$emit('row-edit-cancel', {originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('row-edit-cancel', { originalEvent: event, data: this.rowData, newData: this.editingRowData, field: this.field, index: this.rowIndex });
|
||||
} else {
|
||||
this.switchCellToViewMode();
|
||||
this.$emit('cell-edit-cancel', {originalEvent: event, data: this.rowData, field: this.field, index: this.rowIndex});
|
||||
this.$emit('cell-edit-cancel', { originalEvent: event, data: this.rowData, field: this.field, index: this.rowIndex });
|
||||
}
|
||||
},
|
||||
updateStickyPosition() {
|
||||
if (this.columnProp('frozen')) {
|
||||
let align = this.columnProp('alignFrozen');
|
||||
|
||||
if (align === 'right') {
|
||||
let right = 0;
|
||||
let next = this.$el.nextElementSibling;
|
||||
|
||||
if (next) {
|
||||
right = DomHandler.getOuterWidth(next) + parseFloat(next.style.right || 0);
|
||||
}
|
||||
|
||||
this.styleObject.right = right + 'px';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let left = 0;
|
||||
let prev = this.$el.previousElementSibling;
|
||||
|
||||
if (prev) {
|
||||
left = DomHandler.getOuterWidth(prev) + parseFloat(prev.style.left || 0);
|
||||
}
|
||||
|
||||
this.styleObject.left = left + 'px';
|
||||
}
|
||||
}
|
||||
|
@ -377,41 +387,49 @@ export default {
|
|||
return this.columnProp('field');
|
||||
},
|
||||
containerClass() {
|
||||
return [this.columnProp('bodyClass'), this.columnProp('class'), {
|
||||
'p-selection-column': this.columnProp('selectionMode') != null,
|
||||
'p-editable-column': this.isEditable(),
|
||||
'p-cell-editing': this.d_editing,
|
||||
'p-frozen-column': this.columnProp('frozen')
|
||||
}];
|
||||
return [
|
||||
this.columnProp('bodyClass'),
|
||||
this.columnProp('class'),
|
||||
{
|
||||
'p-selection-column': this.columnProp('selectionMode') != null,
|
||||
'p-editable-column': this.isEditable(),
|
||||
'p-cell-editing': this.d_editing,
|
||||
'p-frozen-column': this.columnProp('frozen')
|
||||
}
|
||||
];
|
||||
},
|
||||
containerStyle() {
|
||||
let bodyStyle = this.columnProp('bodyStyle');
|
||||
let columnStyle = this.columnProp('style');
|
||||
|
||||
return this.columnProp('frozen') ? [columnStyle, bodyStyle, this.styleObject]: [columnStyle, bodyStyle];
|
||||
return this.columnProp('frozen') ? [columnStyle, bodyStyle, this.styleObject] : [columnStyle, bodyStyle];
|
||||
},
|
||||
loading() {
|
||||
return this.getVirtualScrollerProp('loading');
|
||||
},
|
||||
loadingOptions() {
|
||||
const getLoaderOptions = this.getVirtualScrollerProp('getLoaderOptions');
|
||||
return getLoaderOptions && getLoaderOptions(this.rowIndex, {
|
||||
cellIndex: this.index,
|
||||
cellFirst: this.index === 0,
|
||||
cellLast: this.index === (this.getVirtualScrollerProp('columns').length - 1),
|
||||
cellEven: this.index % 2 === 0,
|
||||
cellOdd: this.index % 2 !== 0,
|
||||
column: this.column,
|
||||
field: this.field
|
||||
});
|
||||
|
||||
return (
|
||||
getLoaderOptions &&
|
||||
getLoaderOptions(this.rowIndex, {
|
||||
cellIndex: this.index,
|
||||
cellFirst: this.index === 0,
|
||||
cellLast: this.index === this.getVirtualScrollerProp('columns').length - 1,
|
||||
cellEven: this.index % 2 === 0,
|
||||
cellOdd: this.index % 2 !== 0,
|
||||
column: this.column,
|
||||
field: this.field
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'DTRadioButton': RowRadioButton,
|
||||
'DTCheckbox': RowCheckbox
|
||||
DTRadioButton: RowRadioButton,
|
||||
DTCheckbox: RowCheckbox
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
ripple: Ripple
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,40 +1,73 @@
|
|||
<template>
|
||||
<div :class="containerClass">
|
||||
<div class="p-fluid p-column-filter-element" v-if="display === 'row'" >
|
||||
<div v-if="display === 'row'" class="p-fluid p-column-filter-element">
|
||||
<component :is="filterElement" :field="field" :filterModel="filters[field]" :filterCallback="filterCallback" />
|
||||
</div>
|
||||
<button ref="icon" v-if="showMenuButton" type="button" class="p-column-filter-menu-button p-link" aria-haspopup="true" :aria-expanded="overlayVisible"
|
||||
:class="{'p-column-filter-menu-button-open': overlayVisible, 'p-column-filter-menu-button-active': hasFilter()}"
|
||||
@click="toggleMenu()" @keydown="onToggleButtonKeyDown($event)"><span class="pi pi-filter-icon pi-filter"></span></button>
|
||||
<button v-if="showClearButton && display === 'row'" :class="{'p-hidden-space': !hasRowFilter()}" type="button" class="p-column-filter-clear-button p-link" @click="clearFilter()"><span class="pi pi-filter-slash"></span></button>
|
||||
<button
|
||||
v-if="showMenuButton"
|
||||
ref="icon"
|
||||
type="button"
|
||||
class="p-column-filter-menu-button p-link"
|
||||
aria-haspopup="true"
|
||||
:aria-expanded="overlayVisible"
|
||||
:class="{ 'p-column-filter-menu-button-open': overlayVisible, 'p-column-filter-menu-button-active': hasFilter() }"
|
||||
@click="toggleMenu()"
|
||||
@keydown="onToggleButtonKeyDown($event)"
|
||||
>
|
||||
<span class="pi pi-filter-icon pi-filter"></span>
|
||||
</button>
|
||||
<button v-if="showClearButton && display === 'row'" :class="{ 'p-hidden-space': !hasRowFilter() }" type="button" class="p-column-filter-clear-button p-link" @click="clearFilter()"><span class="pi pi-filter-slash"></span></button>
|
||||
<Portal>
|
||||
<transition name="p-connected-overlay" @enter="onOverlayEnter" @leave="onOverlayLeave" @after-leave="onOverlayAfterLeave">
|
||||
<div :ref="overlayRef" :class="overlayClass" v-if="overlayVisible" @keydown.escape="onEscape" @click="onContentClick" @mousedown="onContentMouseDown">
|
||||
<div v-if="overlayVisible" :ref="overlayRef" :class="overlayClass" @keydown.escape="onEscape" @click="onContentClick" @mousedown="onContentMouseDown">
|
||||
<component :is="filterHeaderTemplate" :field="field" :filterModel="filters[field]" :filterCallback="filterCallback" />
|
||||
<template v-if="display === 'row'">
|
||||
<ul class="p-column-filter-row-items">
|
||||
<li class="p-column-filter-row-item" v-for="(matchMode,i) of matchModes" :key="matchMode.label"
|
||||
@click="onRowMatchModeChange(matchMode.value)" @keydown="onRowMatchModeKeyDown($event)" @keydown.enter.prevent="onRowMatchModeChange(matchMode.value)"
|
||||
:class="{'p-highlight': isRowMatchModeSelected(matchMode.value)}" :tabindex="i === 0 ? '0' : null">{{matchMode.label}}</li>
|
||||
<li
|
||||
v-for="(matchMode, i) of matchModes"
|
||||
:key="matchMode.label"
|
||||
class="p-column-filter-row-item"
|
||||
@click="onRowMatchModeChange(matchMode.value)"
|
||||
@keydown="onRowMatchModeKeyDown($event)"
|
||||
@keydown.enter.prevent="onRowMatchModeChange(matchMode.value)"
|
||||
:class="{ 'p-highlight': isRowMatchModeSelected(matchMode.value) }"
|
||||
:tabindex="i === 0 ? '0' : null"
|
||||
>
|
||||
{{ matchMode.label }}
|
||||
</li>
|
||||
<li class="p-column-filter-separator"></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()">{{ noFilterLabel }}</li>
|
||||
</ul>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="p-column-filter-operator" v-if="isShowOperator">
|
||||
<div v-if="isShowOperator" class="p-column-filter-operator">
|
||||
<CFDropdown :options="operatorOptions" :modelValue="operator" @update:modelValue="onOperatorChange($event)" class="p-column-filter-operator-dropdown" optionLabel="label" optionValue="value"></CFDropdown>
|
||||
</div>
|
||||
<div class="p-column-filter-constraints">
|
||||
<div v-for="(fieldConstraint,i) of fieldConstraints" :key="i" class="p-column-filter-constraint">
|
||||
<CFDropdown v-if="isShowMatchModes" :options="matchModes" :modelValue="fieldConstraint.matchMode" optionLabel="label" optionValue="value"
|
||||
@update:modelValue="onMenuMatchModeChange($event, i)" class="p-column-filter-matchmode-dropdown"></CFDropdown>
|
||||
<div v-for="(fieldConstraint, i) of fieldConstraints" :key="i" class="p-column-filter-constraint">
|
||||
<CFDropdown
|
||||
v-if="isShowMatchModes"
|
||||
:options="matchModes"
|
||||
:modelValue="fieldConstraint.matchMode"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
@update:modelValue="onMenuMatchModeChange($event, i)"
|
||||
class="p-column-filter-matchmode-dropdown"
|
||||
></CFDropdown>
|
||||
<component v-if="display === 'menu'" :is="filterElement" :field="field" :filterModel="fieldConstraint" :filterCallback="filterCallback" />
|
||||
<div>
|
||||
<CFButton v-if="showRemoveIcon" type="button" icon="pi pi-trash" class="p-column-filter-remove-button p-button-text p-button-danger p-button-sm" @click="removeConstraint(i)" :label="removeRuleButtonLabel"></CFButton>
|
||||
<CFButton
|
||||
v-if="showRemoveIcon"
|
||||
type="button"
|
||||
icon="pi pi-trash"
|
||||
class="p-column-filter-remove-button p-button-text p-button-danger p-button-sm"
|
||||
@click="removeConstraint(i)"
|
||||
:label="removeRuleButtonLabel"
|
||||
></CFButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-column-filter-add-rule" v-if="isShowAddConstraint">
|
||||
<div v-if="isShowAddConstraint" class="p-column-filter-add-rule">
|
||||
<CFButton type="button" :label="addRuleButtonLabel" icon="pi pi-plus" class="p-column-filter-add-button p-button-text p-button-sm" @click="addConstraint()"></CFButton>
|
||||
</div>
|
||||
<div class="p-column-filter-buttonbar">
|
||||
|
@ -54,16 +87,16 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler,ConnectedOverlayScrollHandler,ZIndexUtils} from 'primevue/utils';
|
||||
import { DomHandler, ConnectedOverlayScrollHandler, ZIndexUtils } from 'primevue/utils';
|
||||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import {FilterOperator} from 'primevue/api';
|
||||
import { FilterOperator } from 'primevue/api';
|
||||
import Dropdown from 'primevue/dropdown';
|
||||
import Button from 'primevue/button';
|
||||
import Portal from 'primevue/portal';
|
||||
|
||||
export default {
|
||||
name: 'ColumnFilter',
|
||||
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: {
|
||||
field: {
|
||||
type: String,
|
||||
|
@ -140,7 +173,7 @@ export default {
|
|||
overlayVisible: false,
|
||||
defaultMatchMode: null,
|
||||
defaultOperator: null
|
||||
}
|
||||
};
|
||||
},
|
||||
overlay: null,
|
||||
selfClick: false,
|
||||
|
@ -159,24 +192,24 @@ export default {
|
|||
mounted() {
|
||||
if (this.filters && this.filters[this.field]) {
|
||||
let fieldFilters = this.filters[this.field];
|
||||
|
||||
if (fieldFilters.operator) {
|
||||
this.defaultMatchMode = fieldFilters.constraints[0].matchMode;
|
||||
this.defaultOperator = fieldFilters.operator;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.defaultMatchMode = this.filters[this.field].matchMode;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearFilter() {
|
||||
let _filters = {...this.filters};
|
||||
let _filters = { ...this.filters };
|
||||
|
||||
if (_filters[this.field].operator) {
|
||||
_filters[this.field].constraints.splice(1);
|
||||
_filters[this.field].operator = this.defaultOperator;
|
||||
_filters[this.field].constraints[0] = {value: null, matchMode: this.defaultMatchMode};
|
||||
}
|
||||
else {
|
||||
_filters[this.field].constraints[0] = { value: null, matchMode: this.defaultMatchMode };
|
||||
} else {
|
||||
_filters[this.field].value = null;
|
||||
_filters[this.field].matchMode = this.defaultMatchMode;
|
||||
}
|
||||
|
@ -187,18 +220,17 @@ export default {
|
|||
this.hide();
|
||||
},
|
||||
applyFilter() {
|
||||
this.$emit('apply-click', {field: this.field, constraints: this.filters[this.field]});
|
||||
this.$emit('apply-click', { field: this.field, constraints: this.filters[this.field] });
|
||||
this.$emit('filter-apply');
|
||||
this.hide();
|
||||
},
|
||||
hasFilter() {
|
||||
if (this.filtersStore) {
|
||||
let fieldFilter = this.filtersStore[this.field];
|
||||
|
||||
if (fieldFilter) {
|
||||
if (fieldFilter.operator)
|
||||
return !this.isFilterBlank(fieldFilter.constraints[0].value);
|
||||
else
|
||||
return !this.isFilterBlank(fieldFilter.value);
|
||||
if (fieldFilter.operator) return !this.isFilterBlank(fieldFilter.constraints[0].value);
|
||||
else return !this.isFilterBlank(fieldFilter.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,48 +241,51 @@ export default {
|
|||
},
|
||||
isFilterBlank(filter) {
|
||||
if (filter !== null && filter !== undefined) {
|
||||
if ((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
if ((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0)) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
toggleMenu() {
|
||||
this.overlayVisible = !this.overlayVisible;
|
||||
},
|
||||
onToggleButtonKeyDown(event) {
|
||||
switch(event.key) {
|
||||
switch (event.key) {
|
||||
case 'Escape':
|
||||
case 'Tab':
|
||||
this.overlayVisible = false;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'ArrowDown':
|
||||
if (this.overlayVisible) {
|
||||
let focusable = DomHandler.getFocusableElements(this.overlay);
|
||||
|
||||
if (focusable) {
|
||||
focusable[0].focus();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
else if (event.altKey) {
|
||||
} else if (event.altKey) {
|
||||
this.overlayVisible = true;
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEscape() {
|
||||
this.overlayVisible = false;
|
||||
|
||||
if (this.$refs.icon) {
|
||||
this.$refs.icon.focus();
|
||||
}
|
||||
},
|
||||
onRowMatchModeChange(matchMode) {
|
||||
let _filters = {...this.filters};
|
||||
let _filters = { ...this.filters };
|
||||
|
||||
_filters[this.field].matchMode = matchMode;
|
||||
this.$emit('matchmode-change', {field: this.field, matchMode: matchMode});
|
||||
this.$emit('matchmode-change', { field: this.field, matchMode: matchMode });
|
||||
this.$emit('filter-change', _filters);
|
||||
this.$emit('filter-apply');
|
||||
this.hide();
|
||||
|
@ -258,9 +293,10 @@ export default {
|
|||
onRowMatchModeKeyDown(event) {
|
||||
let item = event.target;
|
||||
|
||||
switch(event.key) {
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
var nextItem = this.findNextItem(item);
|
||||
|
||||
if (nextItem) {
|
||||
item.removeAttribute('tabindex');
|
||||
nextItem.tabIndex = '0';
|
||||
|
@ -268,10 +304,11 @@ export default {
|
|||
}
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'ArrowUp':
|
||||
var prevItem = this.findPrevItem(item);
|
||||
|
||||
if (prevItem) {
|
||||
item.removeAttribute('tabindex');
|
||||
prevItem.tabIndex = '0';
|
||||
|
@ -279,36 +316,40 @@ export default {
|
|||
}
|
||||
|
||||
event.preventDefault();
|
||||
break;
|
||||
break;
|
||||
}
|
||||
},
|
||||
isRowMatchModeSelected(matchMode) {
|
||||
return (this.filters[this.field]).matchMode === matchMode;
|
||||
return this.filters[this.field].matchMode === matchMode;
|
||||
},
|
||||
onOperatorChange(value) {
|
||||
let _filters = {...this.filters};
|
||||
let _filters = { ...this.filters };
|
||||
|
||||
_filters[this.field].operator = value;
|
||||
this.$emit('filter-change', _filters);
|
||||
|
||||
this.$emit('operator-change', {field: this.field, operator: value});
|
||||
this.$emit('operator-change', { field: this.field, operator: value });
|
||||
|
||||
if (!this.showApplyButton) {
|
||||
this.$emit('filter-apply');
|
||||
}
|
||||
},
|
||||
onMenuMatchModeChange(value, index) {
|
||||
let _filters = {...this.filters};
|
||||
let _filters = { ...this.filters };
|
||||
|
||||
_filters[this.field].constraints[index].matchMode = value;
|
||||
this.$emit('matchmode-change', {field: this.field, matchMode: value, index: index});
|
||||
this.$emit('matchmode-change', { field: this.field, matchMode: value, index: index });
|
||||
|
||||
if (!this.showApplyButton) {
|
||||
this.$emit('filter-apply');
|
||||
}
|
||||
},
|
||||
addConstraint() {
|
||||
let _filters = {...this.filters};
|
||||
let newConstraint = {value: null, matchMode: this.defaultMatchMode};
|
||||
let _filters = { ...this.filters };
|
||||
let newConstraint = { value: null, matchMode: this.defaultMatchMode };
|
||||
|
||||
_filters[this.field].constraints.push(newConstraint);
|
||||
this.$emit('constraint-add', {field: this.field, constraing: newConstraint});
|
||||
this.$emit('constraint-add', { field: this.field, constraing: newConstraint });
|
||||
this.$emit('filter-change', _filters);
|
||||
|
||||
if (!this.showApplyButton) {
|
||||
|
@ -316,9 +357,10 @@ export default {
|
|||
}
|
||||
},
|
||||
removeConstraint(index) {
|
||||
let _filters = {...this.filters};
|
||||
let _filters = { ...this.filters };
|
||||
let removedConstraint = _filters[this.field].constraints.splice(index, 1);
|
||||
this.$emit('constraint-remove', {field: this.field, constraing: removedConstraint});
|
||||
|
||||
this.$emit('constraint-remove', { field: this.field, constraing: removedConstraint });
|
||||
this.$emit('filter-change', _filters);
|
||||
|
||||
if (!this.showApplyButton) {
|
||||
|
@ -331,18 +373,14 @@ export default {
|
|||
findNextItem(item) {
|
||||
let nextItem = item.nextElementSibling;
|
||||
|
||||
if (nextItem)
|
||||
return DomHandler.hasClass(nextItem, 'p-column-filter-separator') ? this.findNextItem(nextItem) : nextItem;
|
||||
else
|
||||
return item.parentElement.firstElementChild;
|
||||
if (nextItem) return DomHandler.hasClass(nextItem, 'p-column-filter-separator') ? this.findNextItem(nextItem) : nextItem;
|
||||
else return item.parentElement.firstElementChild;
|
||||
},
|
||||
findPrevItem(item) {
|
||||
let prevItem = item.previousElementSibling;
|
||||
|
||||
if (prevItem)
|
||||
DomHandler.hasClass(prevItem, 'p-column-filter-separator') ? this.findPrevItem(prevItem) : prevItem;
|
||||
else
|
||||
return item.parentElement.lastElementChild;
|
||||
if (prevItem) DomHandler.hasClass(prevItem, 'p-column-filter-separator') ? this.findPrevItem(prevItem) : prevItem;
|
||||
else return item.parentElement.lastElementChild;
|
||||
},
|
||||
hide() {
|
||||
this.overlayVisible = false;
|
||||
|
@ -362,6 +400,7 @@ export default {
|
|||
if (this.filterMenuStyle) {
|
||||
DomHandler.applyStyle(this.overlay, this.filterMenuStyle);
|
||||
}
|
||||
|
||||
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
|
||||
DomHandler.absolutePosition(this.overlay, this.$refs.icon);
|
||||
this.bindOutsideClickListener();
|
||||
|
@ -372,7 +411,8 @@ export default {
|
|||
if (!this.isOutsideClicked(e.target)) {
|
||||
this.selfClick = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OverlayEventBus.on('overlay-click', this.overlayEventListener);
|
||||
},
|
||||
onOverlayLeave() {
|
||||
|
@ -404,8 +444,10 @@ export default {
|
|||
if (this.overlayVisible && !this.selfClick && this.isOutsideClicked(event.target)) {
|
||||
this.overlayVisible = false;
|
||||
}
|
||||
|
||||
this.selfClick = false;
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
},
|
||||
|
@ -439,6 +481,7 @@ export default {
|
|||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', this.resizeListener);
|
||||
}
|
||||
},
|
||||
|
@ -451,35 +494,43 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-column-filter p-fluid', {
|
||||
'p-column-filter-row': this.display === 'row',
|
||||
'p-column-filter-menu': this.display === 'menu'
|
||||
}];
|
||||
return [
|
||||
'p-column-filter p-fluid',
|
||||
{
|
||||
'p-column-filter-row': this.display === 'row',
|
||||
'p-column-filter-menu': this.display === 'menu'
|
||||
}
|
||||
];
|
||||
},
|
||||
overlayClass() {
|
||||
return [this.filterMenuClass, {
|
||||
'p-column-filter-overlay p-component p-fluid': true,
|
||||
'p-column-filter-overlay-menu': this.display === 'menu',
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}];
|
||||
return [
|
||||
this.filterMenuClass,
|
||||
{
|
||||
'p-column-filter-overlay p-component p-fluid': true,
|
||||
'p-column-filter-overlay-menu': this.display === 'menu',
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
},
|
||||
showMenuButton() {
|
||||
return this.showMenu && (this.display === 'row' ? this.type !== 'boolean': true);
|
||||
return this.showMenu && (this.display === 'row' ? this.type !== 'boolean' : true);
|
||||
},
|
||||
matchModes() {
|
||||
return this.matchModeOptions ||
|
||||
this.$primevue.config.filterMatchModeOptions[this.type].map(key => {
|
||||
return {label: this.$primevue.config.locale[key], value: key}
|
||||
});
|
||||
return (
|
||||
this.matchModeOptions ||
|
||||
this.$primevue.config.filterMatchModeOptions[this.type].map((key) => {
|
||||
return { label: this.$primevue.config.locale[key], value: key };
|
||||
})
|
||||
);
|
||||
},
|
||||
isShowMatchModes() {
|
||||
return this.type !== 'boolean' && this.showMatchModes && this.matchModes;
|
||||
},
|
||||
operatorOptions() {
|
||||
return [
|
||||
{label: this.$primevue.config.locale.matchAll, value: FilterOperator.AND},
|
||||
{label: this.$primevue.config.locale.matchAny, value: FilterOperator.OR}
|
||||
{ label: this.$primevue.config.locale.matchAll, value: FilterOperator.AND },
|
||||
{ label: this.$primevue.config.locale.matchAny, value: FilterOperator.OR }
|
||||
];
|
||||
},
|
||||
noFilterLabel() {
|
||||
|
@ -504,7 +555,7 @@ export default {
|
|||
return this.$primevue.config.locale.addRule;
|
||||
},
|
||||
isShowAddConstraint() {
|
||||
return this.showAddButton && this.filters[this.field].operator && (this.fieldConstraints && this.fieldConstraints.length < this.maxConstraints);
|
||||
return this.showAddButton && this.filters[this.field].operator && this.fieldConstraints && this.fieldConstraints.length < this.maxConstraints;
|
||||
},
|
||||
clearButtonLabel() {
|
||||
return this.$primevue.config.locale.clear;
|
||||
|
@ -514,9 +565,9 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
'CFDropdown': Dropdown,
|
||||
'CFButton': Button,
|
||||
'Portal': Portal
|
||||
CFDropdown: Dropdown,
|
||||
CFButton: Button,
|
||||
Portal: Portal
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -163,7 +163,7 @@ export interface DataTablePageEvent extends DataTableSortEvent {
|
|||
/**
|
||||
* @extends DataTableSortEvent
|
||||
*/
|
||||
export interface DataTableFilterEvent extends DataTableSortEvent {
|
||||
export interface DataTableFilterEvent extends DataTableSortEvent {
|
||||
/**
|
||||
* Filtered collection (non-lazy only)
|
||||
*/
|
||||
|
@ -188,12 +188,12 @@ export interface DataTableRowClickEvent {
|
|||
/**
|
||||
* @extends DataTableRowClickEvent
|
||||
*/
|
||||
export interface DataTableRowDoubleClickEvent extends DataTableRowClickEvent { }
|
||||
export interface DataTableRowDoubleClickEvent extends DataTableRowClickEvent {}
|
||||
|
||||
/**
|
||||
* @extends DataTableRowClickEvent
|
||||
*/
|
||||
export interface DataTableRowContextMenuEvent extends DataTableRowClickEvent { }
|
||||
export interface DataTableRowContextMenuEvent extends DataTableRowClickEvent {}
|
||||
|
||||
export interface DataTableRowSelectEvent {
|
||||
/**
|
||||
|
@ -217,7 +217,7 @@ export interface DataTableRowSelectEvent {
|
|||
/**
|
||||
* @extends DataTableRowSelectEvent
|
||||
*/
|
||||
export interface DataTableRowUnselectEvent extends DataTableRowSelectEvent { }
|
||||
export interface DataTableRowUnselectEvent extends DataTableRowSelectEvent {}
|
||||
|
||||
export interface DataTableRowSelectAllEvent {
|
||||
/**
|
||||
|
@ -307,7 +307,7 @@ export interface DataTableRowExpandEvent {
|
|||
/**
|
||||
* @extends DataTableRowExpandEvent
|
||||
*/
|
||||
export interface DataTableRowCollapseEvent extends DataTableRowExpandEvent { }
|
||||
export interface DataTableRowCollapseEvent extends DataTableRowExpandEvent {}
|
||||
|
||||
export interface DataTableCellEditInitEvent {
|
||||
/**
|
||||
|
@ -331,7 +331,7 @@ export interface DataTableCellEditInitEvent {
|
|||
/**
|
||||
* @extends DataTableCellEditInitEvent
|
||||
*/
|
||||
export interface DataTableCellEditCancelEvent extends DataTableCellEditInitEvent { }
|
||||
export interface DataTableCellEditCancelEvent extends DataTableCellEditInitEvent {}
|
||||
|
||||
export interface DataTableCellEditCompleteEvent {
|
||||
/**
|
||||
|
@ -394,12 +394,12 @@ export interface DataTableRowEditInitEvent {
|
|||
/**
|
||||
* @extends DataTableRowEditInitEvent
|
||||
*/
|
||||
export interface DataTableRowEditSaveEvent extends DataTableRowEditInitEvent { }
|
||||
export interface DataTableRowEditSaveEvent extends DataTableRowEditInitEvent {}
|
||||
|
||||
/**
|
||||
* @extends DataTableRowEditCancelEvent
|
||||
*/
|
||||
export interface DataTableRowEditCancelEvent extends DataTableRowEditInitEvent { }
|
||||
export interface DataTableRowEditCancelEvent extends DataTableRowEditInitEvent {}
|
||||
|
||||
export interface DataTableStateEvent {
|
||||
/**
|
||||
|
@ -719,7 +719,7 @@ export interface DataTableProps {
|
|||
* A function that takes the row data as a parameter and returns a string to apply a particular class for the row.
|
||||
*
|
||||
*/
|
||||
rowClass?:(data: any) => object | string | undefined;
|
||||
rowClass?: (data: any) => object | string | undefined;
|
||||
/**
|
||||
* A function that takes the row data as a parameter and returns the inline style for the corresponding row.
|
||||
*/
|
||||
|
@ -839,11 +839,11 @@ export interface DataTableSlots {
|
|||
/**
|
||||
* Row data
|
||||
*/
|
||||
data: any;
|
||||
/**
|
||||
* Row index
|
||||
*/
|
||||
index: number;
|
||||
data: any;
|
||||
/**
|
||||
* Row index
|
||||
*/
|
||||
index: number;
|
||||
}) => VNode[];
|
||||
}
|
||||
|
||||
|
@ -882,7 +882,7 @@ export declare type DataTableEmits = {
|
|||
* Emitted when the contextMenuSelection changes.
|
||||
* @param {*} value - New value.
|
||||
*/
|
||||
'update:contextMenuSelection': (value: any[] | any | undefined ) => void;
|
||||
'update:contextMenuSelection': (value: any[] | any | undefined) => void;
|
||||
/**
|
||||
* Emitted when the expandedRows changes.
|
||||
* @param {DataTableExpandedRows} value - New value.
|
||||
|
@ -907,17 +907,17 @@ export declare type DataTableEmits = {
|
|||
* Callback to invoke on pagination. Sort and Filter information is also available for lazy loading implementation.
|
||||
* @param {DataTablePageEvent} event - Custom page event.
|
||||
*/
|
||||
'page': (event: DataTablePageEvent) => void;
|
||||
page: (event: DataTablePageEvent) => void;
|
||||
/**
|
||||
* Callback to invoke on sort. Page and Filter information is also available for lazy loading implementation.
|
||||
* @param {DataTableSortEvent} event - Custom sort event.
|
||||
*/
|
||||
'sort': (event: DataTableSortEvent) => void;
|
||||
sort: (event: DataTableSortEvent) => void;
|
||||
/**
|
||||
* Event to emit after filtering, not triggered in lazy mode.
|
||||
* @param {DataTableFilterEvent} event - Custom filter event.
|
||||
*/
|
||||
'filter': (event: DataTableFilterEvent) => void;
|
||||
filter: (event: DataTableFilterEvent) => void;
|
||||
/**
|
||||
* Callback to invoke after filtering, sorting, pagination and cell editing to pass the rendered value.
|
||||
* @param {*} value - Value displayed by the table.
|
||||
|
@ -1038,7 +1038,7 @@ export declare type DataTableEmits = {
|
|||
* @param {DataTableStateEvent} event - Custom state event.
|
||||
*/
|
||||
'state-save': (event: DataTableStateEvent) => void;
|
||||
}
|
||||
};
|
||||
|
||||
declare class DataTable extends ClassComponent<DataTableProps, DataTableSlots, DataTableEmits> {
|
||||
/**
|
||||
|
@ -1051,7 +1051,7 @@ declare class DataTable extends ClassComponent<DataTableProps, DataTableSlots, D
|
|||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
DataTable: GlobalComponentConstructor<DataTable>
|
||||
DataTable: GlobalComponentConstructor<DataTable>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1066,10 +1066,10 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [DataTable](https://www.primefaces.org/primevue/showcase/#/datatable)
|
||||
* - [Edit](https://www.primefaces.org/primevue/showcase/#/datatable/edit)
|
||||
* - [Sort](https://www.primefaces.org/primevue/showcase/#/datatable/sort)
|
||||
* - [Filter](https://www.primefaces.org/primevue/showcase/#/datatable/filter)
|
||||
* - [DataTable](https://www.primefaces.org/primevue/datatable)
|
||||
* - [Edit](https://www.primefaces.org/primevue/datatable/edit)
|
||||
* - [Sort](https://www.primefaces.org/primevue/datatable/sort)
|
||||
* - [Filter](https://www.primefaces.org/primevue/datatable/filter)
|
||||
* etc.
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -5,78 +5,78 @@ import Row from '@/components/row/Row.vue';
|
|||
import Column from '@/components/column/Column.vue';
|
||||
import Button from '@/components/button/Button.vue';
|
||||
import InputText from '@/components/inputtext/InputText.vue';
|
||||
import {FilterMatchMode} from 'primevue/api';
|
||||
import { FilterMatchMode } from 'primevue/api';
|
||||
|
||||
window.URL.createObjectURL = function() {};
|
||||
window.URL.createObjectURL = function () {};
|
||||
|
||||
const smallData = [
|
||||
{
|
||||
"id": "1000",
|
||||
"code": "vbb124btr",
|
||||
"name": "Game Controller"
|
||||
id: '1000',
|
||||
code: 'vbb124btr',
|
||||
name: 'Game Controller'
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"code": "nvklal433",
|
||||
"name": "Black Watch"
|
||||
id: '1001',
|
||||
code: 'nvklal433',
|
||||
name: 'Black Watch'
|
||||
},
|
||||
{
|
||||
"id": "1002",
|
||||
"code": "zz21cz3c1",
|
||||
"name": "Blue Band"
|
||||
id: '1002',
|
||||
code: 'zz21cz3c1',
|
||||
name: 'Blue Band'
|
||||
}
|
||||
];
|
||||
|
||||
const data = [
|
||||
{
|
||||
"id": "1000",
|
||||
"code": "vbb124btr",
|
||||
"name": "Game Controller"
|
||||
id: '1000',
|
||||
code: 'vbb124btr',
|
||||
name: 'Game Controller'
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"code": "nvklal433",
|
||||
"name": "Black Watch"
|
||||
id: '1001',
|
||||
code: 'nvklal433',
|
||||
name: 'Black Watch'
|
||||
},
|
||||
{
|
||||
"id": "1002",
|
||||
"code": "zz21cz3c1",
|
||||
"name": "Blue Band"
|
||||
id: '1002',
|
||||
code: 'zz21cz3c1',
|
||||
name: 'Blue Band'
|
||||
},
|
||||
{
|
||||
"id": "1003",
|
||||
"code": "244wgerg2",
|
||||
"name": "Blue T-Shirt"
|
||||
id: '1003',
|
||||
code: '244wgerg2',
|
||||
name: 'Blue T-Shirt'
|
||||
},
|
||||
{
|
||||
"id": "1004",
|
||||
"code": "h456wer53",
|
||||
"name": "Bracelet"
|
||||
id: '1004',
|
||||
code: 'h456wer53',
|
||||
name: 'Bracelet'
|
||||
},
|
||||
{
|
||||
"id": "1005",
|
||||
"code": "cm230f032",
|
||||
"name": "Gaming Set"
|
||||
id: '1005',
|
||||
code: 'cm230f032',
|
||||
name: 'Gaming Set'
|
||||
},
|
||||
{
|
||||
"id": "1006",
|
||||
"code": "bib36pfvm",
|
||||
"name": "Chakra Bracelet"
|
||||
id: '1006',
|
||||
code: 'bib36pfvm',
|
||||
name: 'Chakra Bracelet'
|
||||
},
|
||||
{
|
||||
"id": "1007",
|
||||
"code": "mbvjkgip5",
|
||||
"name": "Galaxy Earrings"
|
||||
id: '1007',
|
||||
code: 'mbvjkgip5',
|
||||
name: 'Galaxy Earrings'
|
||||
},
|
||||
{
|
||||
"id": "1008",
|
||||
"code": "f230fh0g3",
|
||||
"name": "Bamboo Watch"
|
||||
id: '1008',
|
||||
code: 'f230fh0g3',
|
||||
name: 'Bamboo Watch'
|
||||
},
|
||||
{
|
||||
"id": "1009",
|
||||
"code": "av2231fwg",
|
||||
"name": "Brown Purse"
|
||||
id: '1009',
|
||||
code: 'av2231fwg',
|
||||
name: 'Brown Purse'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -133,7 +133,6 @@ describe('DataTable.vue', () => {
|
|||
expect(rows[0].findAll('td').length).toEqual(3);
|
||||
});
|
||||
|
||||
|
||||
// table templating
|
||||
it('should have header template', () => {
|
||||
expect(wrapper.find('.p-datatable-header').exists()).toBe(true);
|
||||
|
@ -173,10 +172,8 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.find('.p-paginator-right-content').text()).toBe('Paginator End Templating');
|
||||
});
|
||||
|
||||
|
||||
// column templating
|
||||
|
||||
|
||||
// column grouping
|
||||
it('should exist', () => {
|
||||
wrapper = mount({
|
||||
|
@ -216,24 +213,25 @@ describe('DataTable.vue', () => {
|
|||
data() {
|
||||
return {
|
||||
sales: null
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.sales = [
|
||||
{product: 'Bamboo Watch', lastYearSale: 51, thisYearSale: 40, lastYearProfit: 54406, thisYearProfit: 43342},
|
||||
{product: 'Black Watch', lastYearSale: 83, thisYearSale: 9, lastYearProfit: 423132, thisYearProfit: 312122},
|
||||
{product: 'Blue Band', lastYearSale: 38, thisYearSale: 5, lastYearProfit: 12321, thisYearProfit: 8500}
|
||||
{ product: 'Bamboo Watch', lastYearSale: 51, thisYearSale: 40, lastYearProfit: 54406, thisYearProfit: 43342 },
|
||||
{ product: 'Black Watch', lastYearSale: 83, thisYearSale: 9, lastYearProfit: 423132, thisYearProfit: 312122 },
|
||||
{ product: 'Blue Band', lastYearSale: 38, thisYearSale: 5, lastYearProfit: 12321, thisYearProfit: 8500 }
|
||||
];
|
||||
},
|
||||
methods: {
|
||||
formatCurrency(value) {
|
||||
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
|
||||
return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
lastYearTotal() {
|
||||
let total = 0;
|
||||
for(let sale of this.sales) {
|
||||
|
||||
for (let sale of this.sales) {
|
||||
total += sale.lastYearProfit;
|
||||
}
|
||||
|
||||
|
@ -241,7 +239,8 @@ describe('DataTable.vue', () => {
|
|||
},
|
||||
thisYearTotal() {
|
||||
let total = 0;
|
||||
for(let sale of this.sales) {
|
||||
|
||||
for (let sale of this.sales) {
|
||||
total += sale.thisYearProfit;
|
||||
}
|
||||
|
||||
|
@ -281,7 +280,6 @@ describe('DataTable.vue', () => {
|
|||
expect(footerRows[0].findAll('td')[2].text()).toEqual('This Year Total');
|
||||
});
|
||||
|
||||
|
||||
// sorting
|
||||
it('should single sort', async () => {
|
||||
wrapper = mount(DataTable, {
|
||||
|
@ -422,10 +420,9 @@ describe('DataTable.vue', () => {
|
|||
expect(sortableTH.attributes()['aria-sort']).toBe('none');
|
||||
});
|
||||
|
||||
|
||||
// filtering
|
||||
it('should filtered globally', async () => {
|
||||
await wrapper.setProps({ filters: { 'global': {value: 'b', matchMode: FilterMatchMode.STARTS_WITH} }});
|
||||
await wrapper.setProps({ filters: { global: { value: 'b', matchMode: FilterMatchMode.STARTS_WITH } } });
|
||||
|
||||
await wrapper.vm.filter(smallData);
|
||||
|
||||
|
@ -433,10 +430,7 @@ describe('DataTable.vue', () => {
|
|||
});
|
||||
|
||||
it('should filtered with menu display', async () => {
|
||||
await wrapper.setProps({ filters: { 'name': {value: 'b', matchMode: FilterMatchMode.STARTS_WITH} },
|
||||
filterDisplay: 'menu',
|
||||
globalFilterFields: ['name']
|
||||
});
|
||||
await wrapper.setProps({ filters: { name: { value: 'b', matchMode: FilterMatchMode.STARTS_WITH } }, filterDisplay: 'menu', globalFilterFields: ['name'] });
|
||||
|
||||
await wrapper.vm.filter(smallData);
|
||||
|
||||
|
@ -445,10 +439,7 @@ describe('DataTable.vue', () => {
|
|||
});
|
||||
|
||||
it('should filtered with row display', async () => {
|
||||
await wrapper.setProps({ filters: { 'name': {value: 'b', matchMode: FilterMatchMode.STARTS_WITH} },
|
||||
filterDisplay: 'row',
|
||||
globalFilterFields: ['name']
|
||||
});
|
||||
await wrapper.setProps({ filters: { name: { value: 'b', matchMode: FilterMatchMode.STARTS_WITH } }, filterDisplay: 'row', globalFilterFields: ['name'] });
|
||||
|
||||
await wrapper.vm.filter(smallData);
|
||||
|
||||
|
@ -458,10 +449,10 @@ describe('DataTable.vue', () => {
|
|||
|
||||
// selection
|
||||
it('should single select', async () => {
|
||||
await wrapper.setProps({ selection: null, selectionMode: 'single'});
|
||||
await wrapper.setProps({ selection: null, selectionMode: 'single' });
|
||||
|
||||
await wrapper.vm.onRowClick({
|
||||
originalEvent: {target: wrapper.findAll('tr.p-selectable-row')[0]},
|
||||
originalEvent: { target: wrapper.findAll('tr.p-selectable-row')[0] },
|
||||
data: smallData[0],
|
||||
index: 0
|
||||
});
|
||||
|
@ -472,16 +463,16 @@ describe('DataTable.vue', () => {
|
|||
});
|
||||
|
||||
it('should multiple selection with meta key', async () => {
|
||||
await wrapper.setProps({ selection: null, selectionMode: 'multiple'});
|
||||
await wrapper.setProps({ selection: null, selectionMode: 'multiple' });
|
||||
|
||||
await wrapper.vm.onRowClick({
|
||||
originalEvent: {shiftKey: true, target: wrapper.findAll('tr.p-selectable-row')[0]},
|
||||
originalEvent: { shiftKey: true, target: wrapper.findAll('tr.p-selectable-row')[0] },
|
||||
data: smallData[0],
|
||||
index: 0
|
||||
});
|
||||
|
||||
await wrapper.vm.onRowClick({
|
||||
originalEvent: {shiftKey: true, target: wrapper.findAll('tr.p-selectable-row')[1]},
|
||||
originalEvent: { shiftKey: true, target: wrapper.findAll('tr.p-selectable-row')[1] },
|
||||
data: smallData[1],
|
||||
index: 1
|
||||
});
|
||||
|
@ -492,16 +483,16 @@ describe('DataTable.vue', () => {
|
|||
});
|
||||
|
||||
it('should multiple selection without meta key', async () => {
|
||||
await wrapper.setProps({ selection: null, selectionMode: 'multiple', metaKeySelection: false});
|
||||
await wrapper.setProps({ selection: null, selectionMode: 'multiple', metaKeySelection: false });
|
||||
|
||||
await wrapper.vm.onRowClick({
|
||||
originalEvent: {target: wrapper.findAll('tr.p-selectable-row')[0]},
|
||||
originalEvent: { target: wrapper.findAll('tr.p-selectable-row')[0] },
|
||||
data: smallData[0],
|
||||
index: 0
|
||||
});
|
||||
|
||||
await wrapper.vm.onRowClick({
|
||||
originalEvent: {target: wrapper.findAll('tr.p-selectable-row')[1]},
|
||||
originalEvent: { target: wrapper.findAll('tr.p-selectable-row')[1] },
|
||||
data: smallData[1],
|
||||
index: 1
|
||||
});
|
||||
|
@ -538,12 +529,12 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.findAll('td.p-selection-column').length).toBe(3);
|
||||
expect(wrapper.findAll('.p-radiobutton').length).toBe(3);
|
||||
|
||||
await wrapper.vm.toggleRowWithRadio({originalEvent: {}, data: smallData[0], index: 0});
|
||||
await wrapper.vm.toggleRowWithRadio({ originalEvent: {}, data: smallData[0], index: 0 });
|
||||
|
||||
expect(wrapper.emitted()['update:selection'][0][0]).toEqual(smallData[0]);
|
||||
expect(wrapper.emitted()['row-select'][0][0].index).toBe(0);
|
||||
|
||||
await wrapper.vm.toggleRowWithRadio({originalEvent: {}, data: smallData[1], index: 1});
|
||||
await wrapper.vm.toggleRowWithRadio({ originalEvent: {}, data: smallData[1], index: 1 });
|
||||
|
||||
expect(wrapper.emitted()['update:selection'][1][0]).toEqual(smallData[1]);
|
||||
expect(wrapper.emitted()['row-select'][1][0].index).toBe(1);
|
||||
|
@ -572,12 +563,12 @@ describe('DataTable.vue', () => {
|
|||
|
||||
expect(wrapper.findAll('.p-checkbox').length).toBe(4);
|
||||
|
||||
await wrapper.vm.toggleRowWithCheckbox({originalEvent: {}, data: smallData[0], index: 0});
|
||||
await wrapper.vm.toggleRowWithCheckbox({ originalEvent: {}, data: smallData[0], index: 0 });
|
||||
|
||||
expect(wrapper.emitted()['update:selection'][0][0]).toEqual([smallData[0]]);
|
||||
expect(wrapper.emitted()['row-select'][0][0].index).toBe(0);
|
||||
|
||||
await wrapper.vm.toggleRowWithCheckbox({originalEvent: {}, data: smallData[1], index: 1});
|
||||
await wrapper.vm.toggleRowWithCheckbox({ originalEvent: {}, data: smallData[1], index: 1 });
|
||||
|
||||
expect(wrapper.emitted()['update:selection'][1][0]).toEqual([smallData[1]]);
|
||||
expect(wrapper.emitted()['row-select'][1][0].index).toBe(1);
|
||||
|
@ -603,7 +594,7 @@ describe('DataTable.vue', () => {
|
|||
}
|
||||
});
|
||||
|
||||
await wrapper.vm.toggleRowsWithCheckbox({originalEvent: {}, checked: true});
|
||||
await wrapper.vm.toggleRowsWithCheckbox({ originalEvent: {}, checked: true });
|
||||
|
||||
expect(wrapper.emitted()['row-select-all'][0][0].data).toEqual(smallData);
|
||||
expect(wrapper.emitted()['update:selection'][0][0]).toEqual(smallData);
|
||||
|
@ -629,40 +620,39 @@ describe('DataTable.vue', () => {
|
|||
}
|
||||
});
|
||||
|
||||
await wrapper.vm.toggleRowsWithCheckbox({originalEvent: {}, checked: false});
|
||||
await wrapper.vm.toggleRowsWithCheckbox({ originalEvent: {}, checked: false });
|
||||
|
||||
expect(wrapper.emitted()['row-unselect-all'][0][0].data).toBe(undefined);
|
||||
expect(wrapper.emitted()['update:selection'][0][0]).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
// scrolling
|
||||
it('should scrolling', async () => {
|
||||
await wrapper.setProps({scrollable: true});
|
||||
await wrapper.setProps({ scrollable: true });
|
||||
|
||||
expect(wrapper.find('.p-datatable-scrollable').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should vertical scroll', async () => {
|
||||
await wrapper.setProps({scrollable: true, scrollHeight: '100px'});
|
||||
await wrapper.setProps({ scrollable: true, scrollHeight: '100px' });
|
||||
|
||||
expect(wrapper.find('.p-datatable-wrapper').attributes().style).toBe('max-height: 100px;');
|
||||
});
|
||||
|
||||
it('should flex scrolling', async () => {
|
||||
await wrapper.setProps({scrollable: true, scrollHeight: 'flex'});
|
||||
await wrapper.setProps({ scrollable: true, scrollHeight: 'flex' });
|
||||
|
||||
expect(wrapper.find('.p-datatable-flex-scrollable').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should both scrolling', async () => {
|
||||
await wrapper.setProps({scrollable: true, scrollHeight: '100px', scrollDirection: 'both'});
|
||||
await wrapper.setProps({ scrollable: true, scrollHeight: '100px', scrollDirection: 'both' });
|
||||
|
||||
expect(wrapper.find('.p-datatable-scrollable-both').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should have frozen rows', async () => {
|
||||
await wrapper.setProps({frozenValue: [smallData[0]], scrollable: true, scrollHeight: '100px', scrollDirection: 'both'});
|
||||
await wrapper.setProps({ frozenValue: [smallData[0]], scrollable: true, scrollHeight: '100px', scrollDirection: 'both' });
|
||||
|
||||
expect(wrapper.findAll('.p-datatable-tbody')[0].classes()).toContain('p-datatable-frozen-tbody');
|
||||
expect(wrapper.findAll('.p-datatable-tbody')[0].attributes().style).toBe('top: 0px;');
|
||||
|
@ -697,10 +687,8 @@ describe('DataTable.vue', () => {
|
|||
// expect(wrapper.findAll('td.p-frozen-column')[0].attributes().style).toBe('left: 0px;');
|
||||
});
|
||||
|
||||
|
||||
// lazy loading
|
||||
|
||||
|
||||
// row expansion
|
||||
it('should have row toggler', () => {
|
||||
expect(wrapper.findAll('.p-row-toggler').length).toBe(3);
|
||||
|
@ -709,7 +697,7 @@ describe('DataTable.vue', () => {
|
|||
it('should expand a row', async () => {
|
||||
await wrapper.setProps({ expandedRows: [] });
|
||||
|
||||
await wrapper.vm.toggleRow({ originalEvent: {}, data: smallData[0]});
|
||||
await wrapper.vm.toggleRow({ originalEvent: {}, data: smallData[0] });
|
||||
|
||||
expect(wrapper.emitted()['update:expandedRows'][0][0]).toEqual([smallData[0]]);
|
||||
expect(wrapper.emitted()['row-expand'][0][0].data).toEqual(smallData[0]);
|
||||
|
@ -718,13 +706,12 @@ describe('DataTable.vue', () => {
|
|||
it('should collapse a row', async () => {
|
||||
await wrapper.setProps({ expandedRows: [smallData[0]] });
|
||||
|
||||
await wrapper.vm.toggleRow({ originalEvent: {}, data: smallData[0]});
|
||||
await wrapper.vm.toggleRow({ originalEvent: {}, data: smallData[0] });
|
||||
|
||||
expect(wrapper.emitted()['update:expandedRows'][0][0]).toEqual([]);
|
||||
expect(wrapper.emitted()['row-collapse'][0][0].data).toEqual(smallData[0]);
|
||||
});
|
||||
|
||||
|
||||
// editing
|
||||
// cell editing
|
||||
|
||||
|
@ -799,10 +786,10 @@ describe('DataTable.vue', () => {
|
|||
}
|
||||
});
|
||||
|
||||
await wrapper.vm.onRowEditSave({data: { "id": "9999", "code": "vbb124btr", "name": "Game Controller"}});
|
||||
await wrapper.vm.onRowEditSave({ data: { id: '9999', code: 'vbb124btr', name: 'Game Controller' } });
|
||||
|
||||
expect(wrapper.emitted()['update:editingRows'][0][0]).toEqual([]);
|
||||
expect(wrapper.emitted()['row-edit-save'][0][0].data).toEqual({ "id": "9999", "code": "vbb124btr", "name": "Game Controller"});
|
||||
expect(wrapper.emitted()['row-edit-save'][0][0].data).toEqual({ id: '9999', code: 'vbb124btr', name: 'Game Controller' });
|
||||
});
|
||||
|
||||
it('should cancel row editing', async () => {
|
||||
|
@ -841,7 +828,6 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.emitted()['row-edit-cancel'][0][0].data).toEqual(smallData[0]);
|
||||
});
|
||||
|
||||
|
||||
// column resize
|
||||
it('should fit mode expanding exists', () => {
|
||||
wrapper = mount(DataTable, {
|
||||
|
@ -890,7 +876,7 @@ describe('DataTable.vue', () => {
|
|||
|
||||
const resizer = wrapper.findAll('.p-column-resizer')[0];
|
||||
|
||||
await wrapper.vm.onColumnResizeStart({target: resizer.element});
|
||||
await wrapper.vm.onColumnResizeStart({ target: resizer.element });
|
||||
|
||||
expect(wrapper.componentVM.columnResizing).toBe(true);
|
||||
expect(wrapper.find('.p-column-resizer-helper').attributes().style).toContain('display: none;');
|
||||
|
@ -943,7 +929,7 @@ describe('DataTable.vue', () => {
|
|||
|
||||
const resizer = wrapper.findAll('.p-column-resizer')[0];
|
||||
|
||||
await wrapper.vm.onColumnResizeStart({target: resizer.element});
|
||||
await wrapper.vm.onColumnResizeStart({ target: resizer.element });
|
||||
|
||||
await wrapper.vm.onColumnResizeEnd();
|
||||
|
||||
|
@ -972,7 +958,7 @@ describe('DataTable.vue', () => {
|
|||
|
||||
const resizer = wrapper.findAll('.p-column-resizer')[0];
|
||||
|
||||
await wrapper.vm.onColumnResizeStart({target: resizer.element});
|
||||
await wrapper.vm.onColumnResizeStart({ target: resizer.element });
|
||||
|
||||
expect(wrapper.componentVM.columnResizing).toBe(true);
|
||||
expect(wrapper.find('.p-column-resizer-helper').attributes().style).toContain('display: none;');
|
||||
|
@ -1025,14 +1011,13 @@ describe('DataTable.vue', () => {
|
|||
|
||||
const resizer = wrapper.findAll('.p-column-resizer')[0];
|
||||
|
||||
await wrapper.vm.onColumnResizeStart({target: resizer.element});
|
||||
await wrapper.vm.onColumnResizeStart({ target: resizer.element });
|
||||
|
||||
await wrapper.vm.onColumnResizeEnd();
|
||||
|
||||
expect(wrapper.find('.p-column-resizer-helper').attributes().style).toContain('display: none;');
|
||||
});
|
||||
|
||||
|
||||
// column reorder
|
||||
it('should reorder columns', async () => {
|
||||
await wrapper.setProps({ reorderableColumns: true });
|
||||
|
@ -1041,7 +1026,6 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.find('.p-datatable-reorder-indicator-down').exists()).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
// row reorder
|
||||
it('should exist', () => {
|
||||
wrapper = mount(DataTable, {
|
||||
|
@ -1065,7 +1049,6 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.findAll('.p-datatable-reorderablerow-handle').length).toBe(3);
|
||||
});
|
||||
|
||||
|
||||
// row group
|
||||
// subheader grouping
|
||||
it('should exist', () => {
|
||||
|
@ -1169,81 +1152,81 @@ describe('DataTable.vue', () => {
|
|||
props: {
|
||||
value: [
|
||||
{
|
||||
"id":1000,
|
||||
"name":"James Butt",
|
||||
"country":{
|
||||
"name":"Algeria",
|
||||
"code":"dz"
|
||||
id: 1000,
|
||||
name: 'James Butt',
|
||||
country: {
|
||||
name: 'Algeria',
|
||||
code: 'dz'
|
||||
},
|
||||
"company":"Benton, John B Jr",
|
||||
"representative":{
|
||||
"name":"Ioni Bowcher",
|
||||
"image":"ionibowcher.png"
|
||||
company: 'Benton, John B Jr',
|
||||
representative: {
|
||||
name: 'Ioni Bowcher',
|
||||
image: 'ionibowcher.png'
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":1001,
|
||||
"name":"Josephine Darakjy",
|
||||
"country":{
|
||||
"name":"Egypt",
|
||||
"code":"eg"
|
||||
id: 1001,
|
||||
name: 'Josephine Darakjy',
|
||||
country: {
|
||||
name: 'Egypt',
|
||||
code: 'eg'
|
||||
},
|
||||
"company":"Chanay, Jeffrey A Esq",
|
||||
"representative":{
|
||||
"name":"Amy Elsner",
|
||||
"image":"amyelsner.png"
|
||||
company: 'Chanay, Jeffrey A Esq',
|
||||
representative: {
|
||||
name: 'Amy Elsner',
|
||||
image: 'amyelsner.png'
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":1013,
|
||||
"name":"Graciela Ruta",
|
||||
"country":{
|
||||
"name":"Chile",
|
||||
"code":"cl"
|
||||
id: 1013,
|
||||
name: 'Graciela Ruta',
|
||||
country: {
|
||||
name: 'Chile',
|
||||
code: 'cl'
|
||||
},
|
||||
"company":"Buckley Miller & Wright",
|
||||
"representative":{
|
||||
"name":"Amy Elsner",
|
||||
"image":"amyelsner.png"
|
||||
company: 'Buckley Miller & Wright',
|
||||
representative: {
|
||||
name: 'Amy Elsner',
|
||||
image: 'amyelsner.png'
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":1021,
|
||||
"name":"Veronika Inouye",
|
||||
"country":{
|
||||
"name":"Ecuador",
|
||||
"code":"ec"
|
||||
id: 1021,
|
||||
name: 'Veronika Inouye',
|
||||
country: {
|
||||
name: 'Ecuador',
|
||||
code: 'ec'
|
||||
},
|
||||
"company":"C 4 Network Inc",
|
||||
"representative":{
|
||||
"name":"Ioni Bowcher",
|
||||
"image":"ionibowcher.png"
|
||||
company: 'C 4 Network Inc',
|
||||
representative: {
|
||||
name: 'Ioni Bowcher',
|
||||
image: 'ionibowcher.png'
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":1026,
|
||||
"name":"Chanel Caudy",
|
||||
"country":{
|
||||
"name":"Argentina",
|
||||
"code":"ar"
|
||||
id: 1026,
|
||||
name: 'Chanel Caudy',
|
||||
country: {
|
||||
name: 'Argentina',
|
||||
code: 'ar'
|
||||
},
|
||||
"company":"Professional Image Inc",
|
||||
"representative":{
|
||||
"name":"Ioni Bowcher",
|
||||
"image":"ionibowcher.png"
|
||||
company: 'Professional Image Inc',
|
||||
representative: {
|
||||
name: 'Ioni Bowcher',
|
||||
image: 'ionibowcher.png'
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":1027,
|
||||
"name":"Ezekiel Chui",
|
||||
"country":{
|
||||
"name":"Ireland",
|
||||
"code":"ie"
|
||||
id: 1027,
|
||||
name: 'Ezekiel Chui',
|
||||
country: {
|
||||
name: 'Ireland',
|
||||
code: 'ie'
|
||||
},
|
||||
"company":"Sider, Donald C Esq",
|
||||
"representative":{
|
||||
"name":"Amy Elsner",
|
||||
"image":"amyelsner.png"
|
||||
company: 'Sider, Donald C Esq',
|
||||
representative: {
|
||||
name: 'Amy Elsner',
|
||||
image: 'amyelsner.png'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -1294,34 +1277,34 @@ describe('DataTable.vue', () => {
|
|||
props: {
|
||||
value: [
|
||||
{
|
||||
"id": "1000",
|
||||
"code": "vbb124btr",
|
||||
"name": "Game Controller"
|
||||
id: '1000',
|
||||
code: 'vbb124btr',
|
||||
name: 'Game Controller'
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"code": "nvklal433",
|
||||
"name": "Black Watch"
|
||||
id: '1001',
|
||||
code: 'nvklal433',
|
||||
name: 'Black Watch'
|
||||
},
|
||||
{
|
||||
"id": "1002",
|
||||
"code": "zz21cz3c1",
|
||||
"name": "Blue Band"
|
||||
id: '1002',
|
||||
code: 'zz21cz3c1',
|
||||
name: 'Blue Band'
|
||||
},
|
||||
{
|
||||
"id": "1003",
|
||||
"code": "vbb124btrvbb124btr",
|
||||
"name": "Game Controller"
|
||||
id: '1003',
|
||||
code: 'vbb124btrvbb124btr',
|
||||
name: 'Game Controller'
|
||||
},
|
||||
{
|
||||
"id": "1004",
|
||||
"code": "nvklal433nvklal433",
|
||||
"name": "Black Watch"
|
||||
id: '1004',
|
||||
code: 'nvklal433nvklal433',
|
||||
name: 'Black Watch'
|
||||
},
|
||||
{
|
||||
"id": "1006",
|
||||
"code": "zz21cz3c1zz21cz3c1",
|
||||
"name": "Blue Band"
|
||||
id: '1006',
|
||||
code: 'zz21cz3c1zz21cz3c1',
|
||||
name: 'Blue Band'
|
||||
}
|
||||
],
|
||||
rowGroupMode: 'rowspan',
|
||||
|
@ -1353,7 +1336,6 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.findAll('.p-datatable-tbody > tr')[4].findAll('td')[1].attributes().rowspan).toBe('2');
|
||||
});
|
||||
|
||||
|
||||
// export
|
||||
it('should export table', async () => {
|
||||
const exportCSV = jest.spyOn(wrapper.vm, 'exportCSV');
|
||||
|
@ -1363,7 +1345,6 @@ describe('DataTable.vue', () => {
|
|||
expect(exportCSV).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
// state
|
||||
it('should get storage', async () => {
|
||||
await wrapper.setProps({ stateStorage: 'session', stateKey: 'dt-state-demo-session', paginator: true });
|
||||
|
@ -1393,10 +1374,8 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.emitted()['state-save'][0]).not.toBeNull();
|
||||
});
|
||||
|
||||
|
||||
// contextmenu
|
||||
|
||||
|
||||
// responsive
|
||||
it('should have stack layout', () => {
|
||||
expect(wrapper.find('.p-datatable').classes()).toContain('p-datatable-responsive-stack');
|
||||
|
@ -1408,6 +1387,5 @@ describe('DataTable.vue', () => {
|
|||
expect(wrapper.find('.p-datatable').classes()).toContain('p-datatable-responsive-scroll');
|
||||
});
|
||||
|
||||
|
||||
// row styling
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,12 @@
|
|||
<template>
|
||||
<td :style="containerStyle" :class="containerClass" role="cell"
|
||||
:colspan="columnProp('colspan')" :rowspan="columnProp('rowspan')">
|
||||
<component :is="column.children.footer" :column="column" v-if="column.children && column.children.footer"/>
|
||||
{{columnProp('footer')}}
|
||||
<td :style="containerStyle" :class="containerClass" role="cell" :colspan="columnProp('colspan')" :rowspan="columnProp('rowspan')">
|
||||
<component v-if="column.children && column.children.footer" :is="column.children.footer" :column="column" />
|
||||
{{ columnProp('footer') }}
|
||||
</td>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler,ObjectUtils} from 'primevue/utils';
|
||||
import { DomHandler, ObjectUtils } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'FooterCell',
|
||||
|
@ -20,7 +19,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
styleObject: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (this.columnProp('frozen')) {
|
||||
|
@ -39,20 +38,24 @@ export default {
|
|||
updateStickyPosition() {
|
||||
if (this.columnProp('frozen')) {
|
||||
let align = this.columnProp('alignFrozen');
|
||||
|
||||
if (align === 'right') {
|
||||
let right = 0;
|
||||
let next = this.$el.nextElementSibling;
|
||||
|
||||
if (next) {
|
||||
right = DomHandler.getOuterWidth(next) + parseFloat(next.style.left);
|
||||
}
|
||||
|
||||
this.styleObject.right = right + 'px';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let left = 0;
|
||||
let prev = this.$el.previousElementSibling;
|
||||
|
||||
if (prev) {
|
||||
left = DomHandler.getOuterWidth(prev) + parseFloat(prev.style.left);
|
||||
}
|
||||
|
||||
this.styleObject.left = left + 'px';
|
||||
}
|
||||
}
|
||||
|
@ -60,16 +63,20 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return [this.columnProp('footerClass'), this.columnProp('class'), {
|
||||
'p-frozen-column': this.columnProp('frozen')
|
||||
}];
|
||||
return [
|
||||
this.columnProp('footerClass'),
|
||||
this.columnProp('class'),
|
||||
{
|
||||
'p-frozen-column': this.columnProp('frozen')
|
||||
}
|
||||
];
|
||||
},
|
||||
containerStyle() {
|
||||
let bodyStyle = this.columnProp('footerStyle');
|
||||
let columnStyle = this.columnProp('style');
|
||||
|
||||
return this.columnProp('frozen') ? [columnStyle, bodyStyle, this.styleObject]: [columnStyle, bodyStyle];
|
||||
return this.columnProp('frozen') ? [columnStyle, bodyStyle, this.styleObject] : [columnStyle, bodyStyle];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,37 +1,86 @@
|
|||
<template>
|
||||
<th :style="containerStyle" :class="containerClass" :tabindex="columnProp('sortable') ? '0' : null" role="cell"
|
||||
@click="onClick" @keydown="onKeyDown" @mousedown="onMouseDown"
|
||||
@dragstart="onDragStart" @dragover="onDragOver" @dragleave="onDragLeave" @drop="onDrop"
|
||||
:colspan="columnProp('colspan')" :rowspan="columnProp('rowspan')" :aria-sort="ariaSort">
|
||||
<span class="p-column-resizer" @mousedown="onResizeStart" v-if="resizableColumns && !columnProp('frozen')"></span>
|
||||
<th
|
||||
:style="containerStyle"
|
||||
:class="containerClass"
|
||||
:tabindex="columnProp('sortable') ? '0' : null"
|
||||
role="cell"
|
||||
@click="onClick"
|
||||
@keydown="onKeyDown"
|
||||
@mousedown="onMouseDown"
|
||||
@dragstart="onDragStart"
|
||||
@dragover="onDragOver"
|
||||
@dragleave="onDragLeave"
|
||||
@drop="onDrop"
|
||||
:colspan="columnProp('colspan')"
|
||||
:rowspan="columnProp('rowspan')"
|
||||
:aria-sort="ariaSort"
|
||||
>
|
||||
<span v-if="resizableColumns && !columnProp('frozen')" class="p-column-resizer" @mousedown="onResizeStart"></span>
|
||||
<div class="p-column-header-content">
|
||||
<component :is="column.children.header" :column="column" v-if="column.children && column.children.header"/>
|
||||
<span class="p-column-title" v-if="columnProp('header')">{{columnProp('header')}}</span>
|
||||
<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('sortable')" :class="sortableColumnIcon"></span>
|
||||
<span v-if="isMultiSorted()" class="p-sortable-column-badge">{{getBadgeValue()}}</span>
|
||||
<DTHeaderCheckbox :checked="allRowsSelected" @change="onHeaderCheckboxChange" :disabled="empty" v-if="columnProp('selectionMode') ==='multiple' && filterDisplay !== 'row'" />
|
||||
<DTColumnFilter v-if="filterDisplay === 'menu' && column.children && column.children.filter" :field="columnProp('filterField')||columnProp('field')" :type="columnProp('dataType')" display="menu"
|
||||
:showMenu="columnProp('showFilterMenu')" :filterElement="column.children && column.children.filter"
|
||||
:filterHeaderTemplate="column.children && column.children.filterheader" :filterFooterTemplate="column.children && column.children.filterfooter"
|
||||
:filterClearTemplate="column.children && column.children.filterclear" :filterApplyTemplate="column.children && column.children.filterapply"
|
||||
:filters="filters" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')" :filterMenuStyle="columnProp('filterMenuStyle')" :filterMenuClass="columnProp('filterMenuClass')"
|
||||
:showOperator="columnProp('showFilterOperator')" :showClearButton="columnProp('showClearButton')" :showApplyButton="columnProp('showApplyButton')"
|
||||
:showMatchModes="columnProp('showFilterMatchModes')" :showAddButton="columnProp('showAddButton')" :matchModeOptions="columnProp('filterMatchModeOptions')" :maxConstraints="columnProp('maxConstraints')"
|
||||
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)" @constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
|
||||
<span v-if="isMultiSorted()" class="p-sortable-column-badge">{{ getBadgeValue() }}</span>
|
||||
<DTHeaderCheckbox v-if="columnProp('selectionMode') === 'multiple' && filterDisplay !== 'row'" :checked="allRowsSelected" @change="onHeaderCheckboxChange" :disabled="empty" />
|
||||
<DTColumnFilter
|
||||
v-if="filterDisplay === 'menu' && column.children && column.children.filter"
|
||||
:field="columnProp('filterField') || columnProp('field')"
|
||||
:type="columnProp('dataType')"
|
||||
display="menu"
|
||||
:showMenu="columnProp('showFilterMenu')"
|
||||
:filterElement="column.children && column.children.filter"
|
||||
:filterHeaderTemplate="column.children && column.children.filterheader"
|
||||
:filterFooterTemplate="column.children && column.children.filterfooter"
|
||||
:filterClearTemplate="column.children && column.children.filterclear"
|
||||
:filterApplyTemplate="column.children && column.children.filterapply"
|
||||
:filters="filters"
|
||||
:filtersStore="filtersStore"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
:filterMenuStyle="columnProp('filterMenuStyle')"
|
||||
:filterMenuClass="columnProp('filterMenuClass')"
|
||||
:showOperator="columnProp('showFilterOperator')"
|
||||
:showClearButton="columnProp('showClearButton')"
|
||||
:showApplyButton="columnProp('showApplyButton')"
|
||||
:showMatchModes="columnProp('showFilterMatchModes')"
|
||||
:showAddButton="columnProp('showAddButton')"
|
||||
:matchModeOptions="columnProp('filterMatchModeOptions')"
|
||||
:maxConstraints="columnProp('maxConstraints')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {DomHandler,ObjectUtils} from 'primevue/utils';
|
||||
import { DomHandler, ObjectUtils } from 'primevue/utils';
|
||||
import HeaderCheckbox from './HeaderCheckbox.vue';
|
||||
import ColumnFilter from './ColumnFilter.vue';
|
||||
|
||||
export default {
|
||||
name: 'HeaderCell',
|
||||
emits: ['column-click', 'column-mousedown', 'column-dragstart', 'column-dragover', 'column-dragleave', 'column-drop',
|
||||
'column-resizestart', 'checkbox-change', 'filter-change', 'filter-apply',
|
||||
'operator-change', 'matchmode-change', 'constraint-add', 'constraint-remove', 'filter-clear', 'apply-click'],
|
||||
emits: [
|
||||
'column-click',
|
||||
'column-mousedown',
|
||||
'column-dragstart',
|
||||
'column-dragover',
|
||||
'column-dragleave',
|
||||
'column-drop',
|
||||
'column-resizestart',
|
||||
'checkbox-change',
|
||||
'filter-change',
|
||||
'filter-apply',
|
||||
'operator-change',
|
||||
'matchmode-change',
|
||||
'constraint-add',
|
||||
'constraint-remove',
|
||||
'filter-clear',
|
||||
'apply-click'
|
||||
],
|
||||
props: {
|
||||
column: {
|
||||
type: Object,
|
||||
|
@ -42,7 +91,7 @@ export default {
|
|||
default: false
|
||||
},
|
||||
groupRowsBy: {
|
||||
type: [Array,String],
|
||||
type: [Array, String],
|
||||
default: null
|
||||
},
|
||||
sortMode: {
|
||||
|
@ -97,7 +146,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
styleObject: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (this.columnProp('frozen')) {
|
||||
|
@ -114,15 +163,15 @@ export default {
|
|||
return ObjectUtils.getVNodeProp(this.column, prop);
|
||||
},
|
||||
onClick(event) {
|
||||
this.$emit('column-click', {originalEvent: event, column: this.column});
|
||||
this.$emit('column-click', { originalEvent: event, column: this.column });
|
||||
},
|
||||
onKeyDown(event) {
|
||||
if (event.which === 13 && event.currentTarget.nodeName === 'TH' && DomHandler.hasClass(event.currentTarget, 'p-sortable-column')) {
|
||||
this.$emit('column-click', {originalEvent: event, column: this.column});
|
||||
this.$emit('column-click', { originalEvent: event, column: this.column });
|
||||
}
|
||||
},
|
||||
onMouseDown(event) {
|
||||
this.$emit('column-mousedown', {originalEvent: event, column: this.column});
|
||||
this.$emit('column-mousedown', { originalEvent: event, column: this.column });
|
||||
},
|
||||
onDragStart(event) {
|
||||
this.$emit('column-dragstart', event);
|
||||
|
@ -140,42 +189,48 @@ export default {
|
|||
this.$emit('column-resizestart', event);
|
||||
},
|
||||
getMultiSortMetaIndex() {
|
||||
return this.multiSortMeta.findIndex(meta => (meta.field === this.columnProp('field') || meta.field === this.columnProp('sortField')));
|
||||
return this.multiSortMeta.findIndex((meta) => meta.field === this.columnProp('field') || meta.field === this.columnProp('sortField'));
|
||||
},
|
||||
getBadgeValue() {
|
||||
let index = this.getMultiSortMetaIndex();
|
||||
|
||||
return (this.groupRowsBy && this.groupRowsBy === this.groupRowSortField) && index > -1 ? index : index + 1;
|
||||
return this.groupRowsBy && this.groupRowsBy === this.groupRowSortField && index > -1 ? index : index + 1;
|
||||
},
|
||||
isMultiSorted() {
|
||||
return this.sortMode === 'multiple' && this.columnProp('sortable') && this.getMultiSortMetaIndex() > -1
|
||||
return this.sortMode === 'multiple' && this.columnProp('sortable') && this.getMultiSortMetaIndex() > -1;
|
||||
},
|
||||
isColumnSorted() {
|
||||
return this.sortMode === 'single' ? (this.sortField && (this.sortField === this.columnProp('field') || this.sortField === this.columnProp('sortField'))) : this.isMultiSorted();
|
||||
return this.sortMode === 'single' ? this.sortField && (this.sortField === this.columnProp('field') || this.sortField === this.columnProp('sortField')) : this.isMultiSorted();
|
||||
},
|
||||
updateStickyPosition() {
|
||||
if (this.columnProp('frozen')) {
|
||||
let align = this.columnProp('alignFrozen');
|
||||
|
||||
if (align === 'right') {
|
||||
let right = 0;
|
||||
let next = this.$el.nextElementSibling;
|
||||
|
||||
if (next) {
|
||||
right = DomHandler.getOuterWidth(next) + parseFloat(next.style.right || 0);
|
||||
}
|
||||
|
||||
this.styleObject.right = right + 'px';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let left = 0;
|
||||
let prev = this.$el.previousElementSibling;
|
||||
|
||||
if (prev) {
|
||||
left = DomHandler.getOuterWidth(prev) + parseFloat(prev.style.left || 0);
|
||||
}
|
||||
|
||||
this.styleObject.left = left + 'px';
|
||||
}
|
||||
|
||||
let filterRow = this.$el.parentElement.nextElementSibling;
|
||||
|
||||
if (filterRow) {
|
||||
let index = DomHandler.index(this.$el);
|
||||
|
||||
filterRow.children[index].style.left = this.styleObject.left;
|
||||
filterRow.children[index].style.right = this.styleObject.right;
|
||||
}
|
||||
|
@ -187,20 +242,24 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return [this.filterColumn ? this.columnProp('filterHeaderClass') : this.columnProp('headerClass'), this.columnProp('class'), {
|
||||
return [
|
||||
this.filterColumn ? this.columnProp('filterHeaderClass') : this.columnProp('headerClass'),
|
||||
this.columnProp('class'),
|
||||
{
|
||||
'p-sortable-column': this.columnProp('sortable'),
|
||||
'p-resizable-column': this.resizableColumns,
|
||||
'p-highlight': this.isColumnSorted(),
|
||||
'p-filter-column': this.filterColumn,
|
||||
'p-frozen-column': this.columnProp('frozen'),
|
||||
'p-reorderable-column': this.reorderableColumns
|
||||
}];
|
||||
}
|
||||
];
|
||||
},
|
||||
containerStyle() {
|
||||
let headerStyle = this.filterColumn ? this.columnProp('filterHeaderStyle'): this.columnProp('headerStyle');
|
||||
let headerStyle = this.filterColumn ? this.columnProp('filterHeaderStyle') : this.columnProp('headerStyle');
|
||||
let columnStyle = this.columnProp('style');
|
||||
|
||||
return this.columnProp('frozen') ? [columnStyle, headerStyle, this.styleObject]: [columnStyle, headerStyle];
|
||||
return this.columnProp('frozen') ? [columnStyle, headerStyle, this.styleObject] : [columnStyle, headerStyle];
|
||||
},
|
||||
sortableColumnIcon() {
|
||||
let sorted = false;
|
||||
|
@ -208,10 +267,10 @@ export default {
|
|||
|
||||
if (this.sortMode === 'single') {
|
||||
sorted = this.sortField && (this.sortField === this.columnProp('field') || this.sortField === this.columnProp('sortField'));
|
||||
sortOrder = sorted ? this.sortOrder: 0;
|
||||
}
|
||||
else if (this.sortMode === 'multiple') {
|
||||
sortOrder = sorted ? this.sortOrder : 0;
|
||||
} else if (this.sortMode === 'multiple') {
|
||||
let metaIndex = this.getMultiSortMetaIndex();
|
||||
|
||||
if (metaIndex > -1) {
|
||||
sorted = true;
|
||||
sortOrder = this.multiSortMeta[metaIndex].order;
|
||||
|
@ -219,7 +278,8 @@ export default {
|
|||
}
|
||||
|
||||
return [
|
||||
'p-sortable-column-icon pi pi-fw', {
|
||||
'p-sortable-column-icon pi pi-fw',
|
||||
{
|
||||
'pi-sort-alt': !sorted,
|
||||
'pi-sort-amount-up-alt': sorted && sortOrder > 0,
|
||||
'pi-sort-amount-down': sorted && sortOrder < 0
|
||||
|
@ -229,21 +289,18 @@ export default {
|
|||
ariaSort() {
|
||||
if (this.columnProp('sortable')) {
|
||||
const sortIcon = this.sortableColumnIcon;
|
||||
if (sortIcon[1]['pi-sort-amount-down'])
|
||||
return 'descending';
|
||||
else if (sortIcon[1]['pi-sort-amount-up-alt'])
|
||||
return 'ascending';
|
||||
else
|
||||
return 'none';
|
||||
}
|
||||
else {
|
||||
|
||||
if (sortIcon[1]['pi-sort-amount-down']) return 'descending';
|
||||
else if (sortIcon[1]['pi-sort-amount-up-alt']) return 'ascending';
|
||||
else return 'none';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'DTHeaderCheckbox': HeaderCheckbox,
|
||||
'DTColumnFilter': ColumnFilter
|
||||
DTHeaderCheckbox: HeaderCheckbox,
|
||||
DTColumnFilter: ColumnFilter
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
<template>
|
||||
<div :class="['p-checkbox p-component', {'p-checkbox-focused': focused, 'p-disabled': $attrs.disabled}]" @click="onClick" @keydown.space.prevent="onClick">
|
||||
<div ref="box" :class="['p-checkbox-box p-component', {'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused}]"
|
||||
role="checkbox" :aria-checked="checked" :tabindex="$attrs.disabled ? null : '0'" @focus="onFocus($event)" @blur="onBlur($event)">
|
||||
<span :class="['p-checkbox-icon', {'pi pi-check': checked}]"></span>
|
||||
<div :class="['p-checkbox p-component', { 'p-checkbox-focused': focused, 'p-disabled': $attrs.disabled }]" @click="onClick" @keydown.space.prevent="onClick">
|
||||
<div
|
||||
ref="box"
|
||||
:class="['p-checkbox-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]"
|
||||
role="checkbox"
|
||||
:aria-checked="checked"
|
||||
:tabindex="$attrs.disabled ? null : '0'"
|
||||
@focus="onFocus($event)"
|
||||
@blur="onBlur($event)"
|
||||
>
|
||||
<span :class="['p-checkbox-icon', { 'pi pi-check': checked }]"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -37,5 +44,5 @@ export default {
|
|||
this.focused = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
<template>
|
||||
<div :class="['p-checkbox p-component', {'p-checkbox-focused': focused}]" @click.stop.prevent="onClick">
|
||||
<div ref="box" :class="['p-checkbox-box p-component', {'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused}]"
|
||||
role="checkbox" :aria-checked="checked" :tabindex="$attrs.disabled ? null : '0'" @keydown.space.prevent="onClick" @focus="onFocus($event)" @blur="onBlur($event)">
|
||||
<span :class="['p-checkbox-icon', {'pi pi-check': checked}]"></span>
|
||||
<div :class="['p-checkbox p-component', { 'p-checkbox-focused': focused }]" @click.stop.prevent="onClick">
|
||||
<div
|
||||
ref="box"
|
||||
:class="['p-checkbox-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]"
|
||||
role="checkbox"
|
||||
:aria-checked="checked"
|
||||
:tabindex="$attrs.disabled ? null : '0'"
|
||||
@keydown.space.prevent="onClick"
|
||||
@focus="onFocus($event)"
|
||||
@blur="onBlur($event)"
|
||||
>
|
||||
<span :class="['p-checkbox-icon', { 'pi pi-check': checked }]"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -13,7 +21,7 @@ export default {
|
|||
inheritAttrs: false,
|
||||
emits: ['change'],
|
||||
props: {
|
||||
value: null,
|
||||
value: null,
|
||||
checked: null
|
||||
},
|
||||
data() {
|
||||
|
@ -38,5 +46,5 @@ export default {
|
|||
this.focused = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div :class="['p-radiobutton p-component', {'p-radiobutton-focused': focused}]" @click="onClick" tabindex="0" @focus="onFocus($event)" @blur="onBlur($event)" @keydown.space.prevent="onClick">
|
||||
<div ref="box" :class="['p-radiobutton-box p-component', {'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused}]" role="radio" :aria-checked="checked">
|
||||
<div :class="['p-radiobutton p-component', { 'p-radiobutton-focused': focused }]" @click="onClick" tabindex="0" @focus="onFocus($event)" @blur="onBlur($event)" @keydown.space.prevent="onClick">
|
||||
<div ref="box" :class="['p-radiobutton-box p-component', { 'p-highlight': checked, 'p-disabled': $attrs.disabled, 'p-focus': focused }]" role="radio" :aria-checked="checked">
|
||||
<div class="p-radiobutton-icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@ export default {
|
|||
inheritAttrs: false,
|
||||
emits: ['change'],
|
||||
props: {
|
||||
value: null,
|
||||
value: null,
|
||||
checked: null
|
||||
},
|
||||
data() {
|
||||
|
@ -38,5 +38,5 @@ export default {
|
|||
this.focused = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -2,57 +2,110 @@
|
|||
<tbody :ref="bodyRef" class="p-datatable-tbody" role="rowgroup" :style="bodyStyle">
|
||||
<template v-if="!empty">
|
||||
<template v-for="(rowData, index) of value" :key="getRowKey(rowData, getRowIndex(index)) + '_subheader'">
|
||||
<tr class="p-rowgroup-header" :style="rowGroupHeaderStyle" v-if="templates['groupheader'] && rowGroupMode === 'subheader' && shouldRenderRowGroupHeader(value, rowData, getRowIndex(index))" role="row">
|
||||
<tr v-if="templates['groupheader'] && rowGroupMode === 'subheader' && shouldRenderRowGroupHeader(value, rowData, getRowIndex(index))" class="p-rowgroup-header" :style="rowGroupHeaderStyle" role="row">
|
||||
<td :colspan="columnsLength - 1">
|
||||
<button class="p-row-toggler p-link" @click="onRowGroupToggle($event, rowData)" v-if="expandableRowGroups" type="button">
|
||||
<button v-if="expandableRowGroups" class="p-row-toggler p-link" @click="onRowGroupToggle($event, rowData)" type="button">
|
||||
<span :class="rowGroupTogglerIcon(rowData)"></span>
|
||||
</button>
|
||||
<component :is="templates['groupheader']" :data="rowData" :index="getRowIndex(index)" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr :class="getRowClass(rowData)" :style="rowStyle" :key="getRowKey(rowData, getRowIndex(index))"
|
||||
v-if="expandableRowGroups ? isRowGroupExpanded(rowData): true"
|
||||
@click="onRowClick($event, rowData, getRowIndex(index))" @dblclick="onRowDblClick($event, rowData, getRowIndex(index))" @contextmenu="onRowRightClick($event, rowData, getRowIndex(index))" @touchend="onRowTouchEnd($event)" @keydown="onRowKeyDown($event, rowData, getRowIndex(index))" :tabindex="selectionMode || contextMenu ? '0' : null"
|
||||
@mousedown="onRowMouseDown($event)" @dragstart="onRowDragStart($event, getRowIndex(index))" @dragover="onRowDragOver($event, getRowIndex(index))" @dragleave="onRowDragLeave($event)" @dragend="onRowDragEnd($event)" @drop="onRowDrop($event)" role="row">
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col,'columnKey')||columnProp(col,'field')||i">
|
||||
<DTBodyCell v-if="shouldRenderBodyCell(value, col, getRowIndex(index))" :rowData="rowData" :column="col" :rowIndex="getRowIndex(index)" :index="i" :selected="isSelected(rowData)"
|
||||
:rowTogglerIcon="columnProp(col,'expander') ? rowTogglerIcon(rowData): null" :frozenRow="frozenRow"
|
||||
<tr
|
||||
v-if="expandableRowGroups ? isRowGroupExpanded(rowData) : true"
|
||||
:key="getRowKey(rowData, getRowIndex(index))"
|
||||
:class="getRowClass(rowData)"
|
||||
:style="rowStyle"
|
||||
@click="onRowClick($event, rowData, getRowIndex(index))"
|
||||
@dblclick="onRowDblClick($event, rowData, getRowIndex(index))"
|
||||
@contextmenu="onRowRightClick($event, rowData, getRowIndex(index))"
|
||||
@touchend="onRowTouchEnd($event)"
|
||||
@keydown="onRowKeyDown($event, rowData, getRowIndex(index))"
|
||||
:tabindex="selectionMode || contextMenu ? '0' : null"
|
||||
@mousedown="onRowMouseDown($event)"
|
||||
@dragstart="onRowDragStart($event, getRowIndex(index))"
|
||||
@dragover="onRowDragOver($event, getRowIndex(index))"
|
||||
@dragleave="onRowDragLeave($event)"
|
||||
@dragend="onRowDragEnd($event)"
|
||||
@drop="onRowDrop($event)"
|
||||
role="row"
|
||||
>
|
||||
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
|
||||
<DTBodyCell
|
||||
v-if="shouldRenderBodyCell(value, col, getRowIndex(index))"
|
||||
:rowData="rowData"
|
||||
:column="col"
|
||||
:rowIndex="getRowIndex(index)"
|
||||
:index="i"
|
||||
:selected="isSelected(rowData)"
|
||||
:rowTogglerIcon="columnProp(col, 'expander') ? rowTogglerIcon(rowData) : null"
|
||||
:frozenRow="frozenRow"
|
||||
:rowspan="rowGroupMode === 'rowspan' ? calculateRowGroupSize(value, col, getRowIndex(index)) : null"
|
||||
:editMode="editMode" :editing="editMode === 'row' && isRowEditing(rowData)" :responsiveLayout="responsiveLayout"
|
||||
@radio-change="onRadioChange($event)" @checkbox-change="onCheckboxChange($event)" @row-toggle="onRowToggle($event)"
|
||||
@cell-edit-init="onCellEditInit($event)" @cell-edit-complete="onCellEditComplete($event)" @cell-edit-cancel="onCellEditCancel($event)"
|
||||
@row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"
|
||||
:editingMeta="editingMeta" @editing-meta-change="onEditingMetaChange" :virtualScrollerContentProps="virtualScrollerContentProps"/>
|
||||
:editMode="editMode"
|
||||
:editing="editMode === 'row' && isRowEditing(rowData)"
|
||||
:responsiveLayout="responsiveLayout"
|
||||
@radio-change="onRadioChange($event)"
|
||||
@checkbox-change="onCheckboxChange($event)"
|
||||
@row-toggle="onRowToggle($event)"
|
||||
@cell-edit-init="onCellEditInit($event)"
|
||||
@cell-edit-complete="onCellEditComplete($event)"
|
||||
@cell-edit-cancel="onCellEditCancel($event)"
|
||||
@row-edit-init="onRowEditInit($event)"
|
||||
@row-edit-save="onRowEditSave($event)"
|
||||
@row-edit-cancel="onRowEditCancel($event)"
|
||||
:editingMeta="editingMeta"
|
||||
@editing-meta-change="onEditingMetaChange"
|
||||
:virtualScrollerContentProps="virtualScrollerContentProps"
|
||||
/>
|
||||
</template>
|
||||
</tr>
|
||||
<tr class="p-datatable-row-expansion" v-if="templates['expansion'] && expandedRows && isRowExpanded(rowData)" :key="getRowKey(rowData, getRowIndex(index)) + '_expansion'" role="row">
|
||||
<tr v-if="templates['expansion'] && expandedRows && isRowExpanded(rowData)" :key="getRowKey(rowData, getRowIndex(index)) + '_expansion'" class="p-datatable-row-expansion" role="row">
|
||||
<td :colspan="columnsLength">
|
||||
<component :is="templates['expansion']" :data="rowData" :index="getRowIndex(index)" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="p-rowgroup-footer" v-if="templates['groupfooter'] && rowGroupMode === 'subheader' && shouldRenderRowGroupFooter(value, rowData, getRowIndex(index))" :key="getRowKey(rowData, getRowIndex(index)) + '_subfooter'" 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">
|
||||
<component :is="templates['groupfooter']" :data="rowData" :index="getRowIndex(index)" />
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
<tr v-else class="p-datatable-emptymessage" role="row">
|
||||
<td :colspan="columnsLength">
|
||||
<component :is="templates.empty" v-if="templates.empty" />
|
||||
<component v-if="templates.empty" :is="templates.empty" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ObjectUtils,DomHandler} from 'primevue/utils';
|
||||
import { ObjectUtils, DomHandler } from 'primevue/utils';
|
||||
import BodyCell from './BodyCell.vue';
|
||||
|
||||
export default {
|
||||
name: 'TableBody',
|
||||
emits: ['rowgroup-toggle', 'row-click', 'row-dblclick', 'row-rightclick', 'row-touchend', 'row-keydown', 'row-mousedown',
|
||||
'row-dragstart', 'row-dragover', 'row-dragleave', 'row-dragend', 'row-drop', 'row-toggle',
|
||||
'radio-change', 'checkbox-change', 'cell-edit-init', 'cell-edit-complete', 'cell-edit-cancel',
|
||||
'row-edit-init', 'row-edit-save', 'row-edit-cancel', 'editing-meta-change'],
|
||||
emits: [
|
||||
'rowgroup-toggle',
|
||||
'row-click',
|
||||
'row-dblclick',
|
||||
'row-rightclick',
|
||||
'row-touchend',
|
||||
'row-keydown',
|
||||
'row-mousedown',
|
||||
'row-dragstart',
|
||||
'row-dragover',
|
||||
'row-dragleave',
|
||||
'row-dragend',
|
||||
'row-drop',
|
||||
'row-toggle',
|
||||
'radio-change',
|
||||
'checkbox-change',
|
||||
'cell-edit-init',
|
||||
'cell-edit-complete',
|
||||
'cell-edit-cancel',
|
||||
'row-edit-init',
|
||||
'row-edit-save',
|
||||
'row-edit-cancel',
|
||||
'editing-meta-change'
|
||||
],
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
|
@ -75,7 +128,7 @@ export default {
|
|||
default: null
|
||||
},
|
||||
groupRowsBy: {
|
||||
type: [Array,String],
|
||||
type: [Array, String],
|
||||
default: null
|
||||
},
|
||||
expandableRowGroups: {
|
||||
|
@ -107,7 +160,7 @@ export default {
|
|||
default: null
|
||||
},
|
||||
selection: {
|
||||
type: [Array,Object],
|
||||
type: [Array, Object],
|
||||
default: null
|
||||
},
|
||||
selectionKeys: {
|
||||
|
@ -175,6 +228,11 @@ export default {
|
|||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rowGroupHeaderStyleObject: {}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
virtualScrollerContentProps(newValue, oldValue) {
|
||||
if (!this.isVirtualScrollerDisabled && this.getVirtualScrollerProp('vertical') && this.getVirtualScrollerProp('itemSize', oldValue) !== this.getVirtualScrollerProp('itemSize', newValue)) {
|
||||
|
@ -204,11 +262,6 @@ export default {
|
|||
this.updateFrozenRowGroupHeaderStickyPosition();
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rowGroupHeaderStyleObject: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
columnProp(col, prop) {
|
||||
return ObjectUtils.getVNodeProp(col, prop);
|
||||
|
@ -216,25 +269,28 @@ export default {
|
|||
shouldRenderRowGroupHeader(value, rowData, i) {
|
||||
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||
let prevRowData = value[i - 1];
|
||||
|
||||
if (prevRowData) {
|
||||
let previousRowFieldData = ObjectUtils.resolveFieldData(prevRowData, this.groupRowsBy);
|
||||
|
||||
return currentRowFieldData !== previousRowFieldData;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
getRowKey(rowData, index) {
|
||||
return this.dataKey ? ObjectUtils.resolveFieldData(rowData, this.dataKey): index;
|
||||
return this.dataKey ? ObjectUtils.resolveFieldData(rowData, this.dataKey) : index;
|
||||
},
|
||||
getRowIndex(index) {
|
||||
const getItemOptions = this.getVirtualScrollerProp('getItemOptions');
|
||||
|
||||
return getItemOptions ? getItemOptions(index).index : index;
|
||||
},
|
||||
getRowClass(rowData) {
|
||||
let rowStyleClass = [];
|
||||
|
||||
if (this.selectionMode) {
|
||||
rowStyleClass.push('p-selectable-row');
|
||||
rowStyleClass.push('p-selectable-row');
|
||||
}
|
||||
|
||||
if (this.selection) {
|
||||
|
@ -262,15 +318,15 @@ export default {
|
|||
shouldRenderRowGroupFooter(value, rowData, i) {
|
||||
if (this.expandableRowGroups && !this.isRowGroupExpanded(rowData)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let currentRowFieldData = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||
let nextRowData = value[i + 1];
|
||||
|
||||
if (nextRowData) {
|
||||
let nextRowFieldData = ObjectUtils.resolveFieldData(nextRowData, this.groupRowsBy);
|
||||
|
||||
return currentRowFieldData !== nextRowFieldData;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -279,25 +335,23 @@ export default {
|
|||
if (this.rowGroupMode) {
|
||||
if (this.rowGroupMode === 'subheader') {
|
||||
return this.groupRowsBy !== this.columnProp(column, 'field');
|
||||
}
|
||||
else if (this.rowGroupMode === 'rowspan') {
|
||||
} else if (this.rowGroupMode === 'rowspan') {
|
||||
if (this.isGrouped(column)) {
|
||||
let prevRowData = value[i - 1];
|
||||
|
||||
if (prevRowData) {
|
||||
let currentRowFieldData = ObjectUtils.resolveFieldData(value[i], this.columnProp(column, 'field'));
|
||||
let previousRowFieldData = ObjectUtils.resolveFieldData(prevRowData, this.columnProp(column, 'field'));
|
||||
|
||||
return currentRowFieldData !== previousRowFieldData;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return !this.columnProp(column, 'hidden');
|
||||
}
|
||||
},
|
||||
|
@ -310,55 +364,49 @@ export default {
|
|||
while (currentRowFieldData === nextRowFieldData) {
|
||||
groupRowSpan++;
|
||||
let nextRowData = value[++index];
|
||||
|
||||
if (nextRowData) {
|
||||
nextRowFieldData = ObjectUtils.resolveFieldData(nextRowData, this.columnProp(column, 'field'));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return groupRowSpan === 1 ? null : groupRowSpan;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
rowTogglerIcon(rowData) {
|
||||
const icon = this.isRowExpanded(rowData) ? this.expandedRowIcon : this.collapsedRowIcon;
|
||||
|
||||
return ['p-row-toggler-icon pi', icon];
|
||||
},
|
||||
rowGroupTogglerIcon(rowData) {
|
||||
const icon = this.isRowGroupExpanded(rowData) ? this.expandedRowIcon : this.collapsedRowIcon;
|
||||
|
||||
return ['p-row-toggler-icon pi', icon];
|
||||
},
|
||||
isGrouped(column) {
|
||||
if (this.groupRowsBy && this.columnProp(column, 'field')) {
|
||||
if (Array.isArray(this.groupRowsBy))
|
||||
return this.groupRowsBy.indexOf(column.props.field) > -1;
|
||||
else
|
||||
return this.groupRowsBy === column.props.field;
|
||||
}
|
||||
else {
|
||||
if (Array.isArray(this.groupRowsBy)) return this.groupRowsBy.indexOf(column.props.field) > -1;
|
||||
else return this.groupRowsBy === column.props.field;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isRowEditing(rowData) {
|
||||
if (rowData && this.editingRows) {
|
||||
if (this.dataKey)
|
||||
return this.editingRowKeys ? this.editingRowKeys[ObjectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined : false;
|
||||
else
|
||||
return this.findIndex(rowData, this.editingRows) > -1;
|
||||
if (this.dataKey) return this.editingRowKeys ? this.editingRowKeys[ObjectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined : false;
|
||||
else return this.findIndex(rowData, this.editingRows) > -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
isRowExpanded(rowData) {
|
||||
if (rowData && this.expandedRows) {
|
||||
if (this.dataKey)
|
||||
return this.expandedRowKeys ? this.expandedRowKeys[ObjectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined : false;
|
||||
else
|
||||
return this.findIndex(rowData, this.expandedRows) > -1;
|
||||
if (this.dataKey) return this.expandedRowKeys ? this.expandedRowKeys[ObjectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined : false;
|
||||
else return this.findIndex(rowData, this.expandedRows) > -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -366,20 +414,19 @@ export default {
|
|||
isRowGroupExpanded(rowData) {
|
||||
if (this.expandableRowGroups && this.expandedRowGroups) {
|
||||
let groupFieldValue = ObjectUtils.resolveFieldData(rowData, this.groupRowsBy);
|
||||
|
||||
return this.expandedRowGroups.indexOf(groupFieldValue) > -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
isSelected(rowData) {
|
||||
if (rowData && this.selection) {
|
||||
if (this.dataKey) {
|
||||
return this.selectionKeys ? this.selectionKeys[ObjectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined : false;
|
||||
}
|
||||
else {
|
||||
if (this.selection instanceof Array)
|
||||
return this.findIndexInSelection(rowData) > -1;
|
||||
else
|
||||
return this.equals(rowData, this.selection);
|
||||
} else {
|
||||
if (this.selection instanceof Array) return this.findIndexInSelection(rowData) > -1;
|
||||
else return this.equals(rowData, this.selection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,6 +444,7 @@ export default {
|
|||
},
|
||||
findIndex(rowData, collection) {
|
||||
let index = -1;
|
||||
|
||||
if (collection && collection.length) {
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
if (this.equals(rowData, collection[i])) {
|
||||
|
@ -409,34 +457,34 @@ export default {
|
|||
return index;
|
||||
},
|
||||
equals(data1, data2) {
|
||||
return this.compareSelectionBy === 'equals' ? (data1 === data2) : ObjectUtils.equals(data1, data2, this.dataKey);
|
||||
return this.compareSelectionBy === 'equals' ? data1 === data2 : ObjectUtils.equals(data1, data2, this.dataKey);
|
||||
},
|
||||
onRowGroupToggle(event, data) {
|
||||
this.$emit('rowgroup-toggle', {originalEvent: event, data: data});
|
||||
this.$emit('rowgroup-toggle', { originalEvent: event, data: data });
|
||||
},
|
||||
onRowClick(event, rowData, rowIndex) {
|
||||
this.$emit('row-click', {originalEvent: event, data: rowData, index: rowIndex});
|
||||
this.$emit('row-click', { originalEvent: event, data: rowData, index: rowIndex });
|
||||
},
|
||||
onRowDblClick(event, rowData, rowIndex) {
|
||||
this.$emit('row-dblclick', {originalEvent: event, data: rowData, index: rowIndex});
|
||||
this.$emit('row-dblclick', { originalEvent: event, data: rowData, index: rowIndex });
|
||||
},
|
||||
onRowRightClick(event, rowData, rowIndex) {
|
||||
this.$emit('row-rightclick', {originalEvent: event, data: rowData, index: rowIndex});
|
||||
this.$emit('row-rightclick', { originalEvent: event, data: rowData, index: rowIndex });
|
||||
},
|
||||
onRowTouchEnd(event) {
|
||||
this.$emit('row-touchend', event);
|
||||
},
|
||||
onRowKeyDown(event, rowData, rowIndex) {
|
||||
this.$emit('row-keydown', {originalEvent: event, data: rowData, index: rowIndex});
|
||||
this.$emit('row-keydown', { originalEvent: event, data: rowData, index: rowIndex });
|
||||
},
|
||||
onRowMouseDown(event) {
|
||||
this.$emit('row-mousedown', event);
|
||||
},
|
||||
onRowDragStart(event, rowIndex) {
|
||||
this.$emit('row-dragstart', {originalEvent: event, index: rowIndex});
|
||||
this.$emit('row-dragstart', { originalEvent: event, index: rowIndex });
|
||||
},
|
||||
onRowDragOver(event, rowIndex) {
|
||||
this.$emit('row-dragover', {originalEvent: event, index: rowIndex});
|
||||
this.$emit('row-dragover', { originalEvent: event, index: rowIndex });
|
||||
},
|
||||
onRowDragLeave(event) {
|
||||
this.$emit('row-dragleave', event);
|
||||
|
@ -482,19 +530,23 @@ export default {
|
|||
},
|
||||
updateFrozenRowGroupHeaderStickyPosition() {
|
||||
let tableHeaderHeight = DomHandler.getOuterHeight(this.$el.previousElementSibling);
|
||||
this.rowGroupHeaderStyleObject.top = tableHeaderHeight + 'px'
|
||||
|
||||
this.rowGroupHeaderStyleObject.top = tableHeaderHeight + 'px';
|
||||
},
|
||||
updateVirtualScrollerPosition() {
|
||||
const tableHeaderHeight = DomHandler.getOuterHeight(this.$el.previousElementSibling);
|
||||
|
||||
this.$el.style.top = (this.$el.style.top || 0) + tableHeaderHeight + 'px';
|
||||
},
|
||||
getVirtualScrollerProp(option, options) {
|
||||
options = options || this.virtualScrollerContentProps;
|
||||
|
||||
return options ? options[option] : null;
|
||||
},
|
||||
bodyRef(el) {
|
||||
// For VirtualScroller
|
||||
const contentRef = this.getVirtualScrollerProp('contentRef');
|
||||
|
||||
contentRef && contentRef(el);
|
||||
}
|
||||
},
|
||||
|
@ -502,15 +554,15 @@ export default {
|
|||
columnsLength() {
|
||||
let hiddenColLength = 0;
|
||||
|
||||
this.columns.forEach(column => {
|
||||
if(this.columnProp(column, 'hidden')) hiddenColLength++;
|
||||
this.columns.forEach((column) => {
|
||||
if (this.columnProp(column, 'hidden')) hiddenColLength++;
|
||||
});
|
||||
|
||||
return this.columns ? this.columns.length - hiddenColLength : 0;
|
||||
},
|
||||
rowGroupHeaderStyle() {
|
||||
if (this.scrollable) {
|
||||
return {top: this.rowGroupHeaderStyleObject.top};
|
||||
return { top: this.rowGroupHeaderStyleObject.top };
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -520,7 +572,7 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
'DTBodyCell': BodyCell
|
||||
DTBodyCell: BodyCell
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<tfoot class="p-datatable-tfoot" v-if="hasFooter" role="rowgroup">
|
||||
<tfoot v-if="hasFooter" class="p-datatable-tfoot" role="rowgroup">
|
||||
<tr v-if="!columnGroup" role="row">
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col,'columnKey')||columnProp(col,'field')||i" >
|
||||
<DTFooterCell :column="col" v-if="!columnProp(col,'hidden')"/>
|
||||
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
|
||||
<DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" />
|
||||
</template>
|
||||
</tr>
|
||||
<template v-else>
|
||||
<tr v-for="(row,i) of getFooterRows()" :key="i" role="row">
|
||||
<template v-for="(col,j) of getFooterColumns(row)" :key="columnProp(col,'columnKey')||columnProp(col,'field')||j">
|
||||
<DTFooterCell :column="col" v-if="!columnProp(col,'hidden')"/>
|
||||
<tr v-for="(row, i) of getFooterRows()" :key="i" role="row">
|
||||
<template v-for="(col, j) of getFooterColumns(row)" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || j">
|
||||
<DTFooterCell v-if="!columnProp(col, 'hidden')" :column="col" />
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
<script>
|
||||
import FooterCell from './FooterCell.vue';
|
||||
import {ObjectUtils} from 'primevue/utils';
|
||||
import { ObjectUtils } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'TableFooter',
|
||||
|
@ -29,7 +29,7 @@ export default {
|
|||
columns: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
columnProp(col, prop) {
|
||||
|
@ -39,12 +39,12 @@ export default {
|
|||
let rows = [];
|
||||
|
||||
let columnGroup = this.columnGroup;
|
||||
|
||||
if (columnGroup.children && columnGroup.children.default) {
|
||||
for (let child of columnGroup.children.default()) {
|
||||
if (child.type.name === 'Row') {
|
||||
rows.push(child);
|
||||
}
|
||||
else if (child.children && child.children instanceof Array) {
|
||||
} else if (child.children && child.children instanceof Array) {
|
||||
rows = child.children;
|
||||
}
|
||||
}
|
||||
|
@ -52,15 +52,13 @@ export default {
|
|||
return rows;
|
||||
}
|
||||
},
|
||||
getFooterColumns(row){
|
||||
getFooterColumns(row) {
|
||||
let cols = [];
|
||||
|
||||
if (row.children && row.children.default) {
|
||||
row.children.default().forEach(child => {
|
||||
if (child.children && child.children instanceof Array)
|
||||
cols = [...cols, ...child.children];
|
||||
else if (child.type.name === 'Column')
|
||||
cols.push(child);
|
||||
row.children.default().forEach((child) => {
|
||||
if (child.children && child.children instanceof Array) cols = [...cols, ...child.children];
|
||||
else if (child.type.name === 'Column') cols.push(child);
|
||||
});
|
||||
|
||||
return cols;
|
||||
|
@ -73,8 +71,7 @@ export default {
|
|||
|
||||
if (this.columnGroup) {
|
||||
hasFooter = true;
|
||||
}
|
||||
else if (this.columns) {
|
||||
} else if (this.columns) {
|
||||
for (let col of this.columns) {
|
||||
if (this.columnProp(col, 'footer') || (col.children && col.children.footer)) {
|
||||
hasFooter = true;
|
||||
|
@ -87,7 +84,7 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
'DTFooterCell': FooterCell
|
||||
DTFooterCell: FooterCell
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -2,45 +2,107 @@
|
|||
<thead class="p-datatable-thead" role="rowgroup">
|
||||
<template v-if="!columnGroup">
|
||||
<tr role="row">
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<DTHeaderCell v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || (groupRowsBy !== columnProp(col, 'field')))" :column="col"
|
||||
@column-click="$emit('column-click', $event)" @column-mousedown="$emit('column-mousedown', $event)"
|
||||
@column-dragstart="$emit('column-dragstart', $event)" @column-dragover="$emit('column-dragover', $event)" @column-dragleave="$emit('column-dragleave', $event)" @column-drop="$emit('column-drop', $event)"
|
||||
:groupRowsBy="groupRowsBy" :groupRowSortField="groupRowSortField" :reorderableColumns="reorderableColumns" :resizableColumns="resizableColumns" @column-resizestart="$emit('column-resizestart', $event)"
|
||||
:sortMode="sortMode" :sortField="sortField" :sortOrder="sortOrder" :multiSortMeta="multiSortMeta"
|
||||
:allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('checkbox-change', $event)"
|
||||
:filters="filters" :filterDisplay="filterDisplay" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')"
|
||||
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
|
||||
<template v-for="(col, i) of columns" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || i">
|
||||
<DTHeaderCell
|
||||
v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field'))"
|
||||
:column="col"
|
||||
@column-click="$emit('column-click', $event)"
|
||||
@column-mousedown="$emit('column-mousedown', $event)"
|
||||
@column-dragstart="$emit('column-dragstart', $event)"
|
||||
@column-dragover="$emit('column-dragover', $event)"
|
||||
@column-dragleave="$emit('column-dragleave', $event)"
|
||||
@column-drop="$emit('column-drop', $event)"
|
||||
:groupRowsBy="groupRowsBy"
|
||||
:groupRowSortField="groupRowSortField"
|
||||
:reorderableColumns="reorderableColumns"
|
||||
:resizableColumns="resizableColumns"
|
||||
@column-resizestart="$emit('column-resizestart', $event)"
|
||||
:sortMode="sortMode"
|
||||
:sortField="sortField"
|
||||
:sortOrder="sortOrder"
|
||||
:multiSortMeta="multiSortMeta"
|
||||
:allRowsSelected="allRowsSelected"
|
||||
:empty="empty"
|
||||
@checkbox-change="$emit('checkbox-change', $event)"
|
||||
:filters="filters"
|
||||
:filterDisplay="filterDisplay"
|
||||
:filtersStore="filtersStore"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
/>
|
||||
</template>
|
||||
</tr>
|
||||
<tr v-if="filterDisplay === 'row'" role="row">
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<th :style="getFilterColumnHeaderStyle(col)" :class="getFilterColumnHeaderClass(col)" v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || (groupRowsBy !== columnProp(col, 'field')))">
|
||||
<DTHeaderCheckbox :checked="allRowsSelected" @change="$emit('checkbox-change', $event)" :disabled="empty" v-if="columnProp(col, 'selectionMode') ==='multiple'" />
|
||||
<DTColumnFilter v-if="col.children && col.children.filter" :field="columnProp(col,'filterField')||columnProp(col,'field')" :type="columnProp(col,'dataType')" display="row"
|
||||
:showMenu="columnProp(col,'showFilterMenu')" :filterElement="col.children && col.children.filter"
|
||||
:filterHeaderTemplate="col.children && col.children.filterheader" :filterFooterTemplate="col.children && col.children.filterfooter"
|
||||
:filterClearTemplate="col.children && col.children.filterclear" :filterApplyTemplate="col.children && col.children.filterapply"
|
||||
:filters="filters" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')" :filterMenuStyle="columnProp(col,'filterMenuStyle')" :filterMenuClass="columnProp(col,'filterMenuClass')"
|
||||
:showOperator="columnProp(col,'showFilterOperator')" :showClearButton="columnProp(col,'showClearButton')" :showApplyButton="columnProp(col,'showApplyButton')"
|
||||
:showMatchModes="columnProp(col,'showFilterMatchModes')" :showAddButton="columnProp(col,'showAddButton')" :matchModeOptions="columnProp(col,'filterMatchModeOptions')" :maxConstraints="columnProp(col,'maxConstraints')"
|
||||
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)" @constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
|
||||
<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)">
|
||||
<DTHeaderCheckbox v-if="columnProp(col, 'selectionMode') === 'multiple'" :checked="allRowsSelected" @change="$emit('checkbox-change', $event)" :disabled="empty" />
|
||||
<DTColumnFilter
|
||||
v-if="col.children && col.children.filter"
|
||||
:field="columnProp(col, 'filterField') || columnProp(col, 'field')"
|
||||
:type="columnProp(col, 'dataType')"
|
||||
display="row"
|
||||
:showMenu="columnProp(col, 'showFilterMenu')"
|
||||
:filterElement="col.children && col.children.filter"
|
||||
:filterHeaderTemplate="col.children && col.children.filterheader"
|
||||
:filterFooterTemplate="col.children && col.children.filterfooter"
|
||||
:filterClearTemplate="col.children && col.children.filterclear"
|
||||
:filterApplyTemplate="col.children && col.children.filterapply"
|
||||
:filters="filters"
|
||||
:filtersStore="filtersStore"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
:filterMenuStyle="columnProp(col, 'filterMenuStyle')"
|
||||
:filterMenuClass="columnProp(col, 'filterMenuClass')"
|
||||
:showOperator="columnProp(col, 'showFilterOperator')"
|
||||
:showClearButton="columnProp(col, 'showClearButton')"
|
||||
:showApplyButton="columnProp(col, 'showApplyButton')"
|
||||
:showMatchModes="columnProp(col, 'showFilterMatchModes')"
|
||||
:showAddButton="columnProp(col, 'showAddButton')"
|
||||
:matchModeOptions="columnProp(col, 'filterMatchModeOptions')"
|
||||
:maxConstraints="columnProp(col, 'maxConstraints')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
/>
|
||||
</th>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
<template v-else>
|
||||
<tr v-for="(row,i) of getHeaderRows()" :key="i" role="row">
|
||||
<template v-for="(col,j) of getHeaderColumns(row)" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||j">
|
||||
<DTHeaderCell v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || (groupRowsBy !== columnProp(col, 'field'))) && (typeof col.children !== 'string')" :column="col"
|
||||
@column-click="$emit('column-click', $event)" @column-mousedown="$emit('column-mousedown', $event)"
|
||||
:groupRowsBy="groupRowsBy" :groupRowSortField="groupRowSortField" :sortMode="sortMode" :sortField="sortField" :sortOrder="sortOrder" :multiSortMeta="multiSortMeta"
|
||||
:allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('checkbox-change', $event)"
|
||||
:filters="filters" :filterDisplay="filterDisplay" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')"
|
||||
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
|
||||
<tr v-for="(row, i) of getHeaderRows()" :key="i" role="row">
|
||||
<template v-for="(col, j) of getHeaderColumns(row)" :key="columnProp(col, 'columnKey') || columnProp(col, 'field') || j">
|
||||
<DTHeaderCell
|
||||
v-if="!columnProp(col, 'hidden') && (rowGroupMode !== 'subheader' || groupRowsBy !== columnProp(col, 'field')) && typeof col.children !== 'string'"
|
||||
:column="col"
|
||||
@column-click="$emit('column-click', $event)"
|
||||
@column-mousedown="$emit('column-mousedown', $event)"
|
||||
:groupRowsBy="groupRowsBy"
|
||||
:groupRowSortField="groupRowSortField"
|
||||
:sortMode="sortMode"
|
||||
:sortField="sortField"
|
||||
:sortOrder="sortOrder"
|
||||
:multiSortMeta="multiSortMeta"
|
||||
:allRowsSelected="allRowsSelected"
|
||||
:empty="empty"
|
||||
@checkbox-change="$emit('checkbox-change', $event)"
|
||||
:filters="filters"
|
||||
:filterDisplay="filterDisplay"
|
||||
:filtersStore="filtersStore"
|
||||
@filter-change="$emit('filter-change', $event)"
|
||||
@filter-apply="$emit('filter-apply')"
|
||||
@operator-change="$emit('operator-change', $event)"
|
||||
@matchmode-change="$emit('matchmode-change', $event)"
|
||||
@constraint-add="$emit('constraint-add', $event)"
|
||||
@constraint-remove="$emit('constraint-remove', $event)"
|
||||
@apply-click="$emit('apply-click', $event)"
|
||||
/>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
|
@ -51,15 +113,30 @@
|
|||
import HeaderCell from './HeaderCell.vue';
|
||||
import HeaderCheckbox from './HeaderCheckbox.vue';
|
||||
import ColumnFilter from './ColumnFilter.vue';
|
||||
import {ObjectUtils} from 'primevue/utils';
|
||||
import { ObjectUtils } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'TableHeader',
|
||||
emits: ['column-click', 'column-mousedown', 'column-dragstart', 'column-dragover', 'column-dragleave', 'column-drop',
|
||||
'column-resizestart', 'checkbox-change', 'filter-change', 'filter-apply',
|
||||
'operator-change', 'matchmode-change', 'constraint-add', 'constraint-remove', 'filter-clear', 'apply-click'],
|
||||
emits: [
|
||||
'column-click',
|
||||
'column-mousedown',
|
||||
'column-dragstart',
|
||||
'column-dragover',
|
||||
'column-dragleave',
|
||||
'column-drop',
|
||||
'column-resizestart',
|
||||
'checkbox-change',
|
||||
'filter-change',
|
||||
'filter-apply',
|
||||
'operator-change',
|
||||
'matchmode-change',
|
||||
'constraint-add',
|
||||
'constraint-remove',
|
||||
'filter-clear',
|
||||
'apply-click'
|
||||
],
|
||||
props: {
|
||||
columnGroup: {
|
||||
columnGroup: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
|
@ -72,7 +149,7 @@ export default {
|
|||
default: null
|
||||
},
|
||||
groupRowsBy: {
|
||||
type: [Array,String],
|
||||
type: [Array, String],
|
||||
default: null
|
||||
},
|
||||
resizableColumns: {
|
||||
|
@ -129,9 +206,14 @@ export default {
|
|||
return ObjectUtils.getVNodeProp(col, prop);
|
||||
},
|
||||
getFilterColumnHeaderClass(column) {
|
||||
return ['p-filter-column', this.columnProp(column, 'filterHeaderClass'), this.columnProp(column, 'class'), {
|
||||
'p-frozen-column': this.columnProp(column, 'frozen')
|
||||
}];
|
||||
return [
|
||||
'p-filter-column',
|
||||
this.columnProp(column, 'filterHeaderClass'),
|
||||
this.columnProp(column, 'class'),
|
||||
{
|
||||
'p-frozen-column': this.columnProp(column, 'frozen')
|
||||
}
|
||||
];
|
||||
},
|
||||
getFilterColumnHeaderStyle(column) {
|
||||
return [this.columnProp(column, 'filterHeaderStyle'), this.columnProp(column, 'style')];
|
||||
|
@ -140,12 +222,12 @@ export default {
|
|||
let rows = [];
|
||||
|
||||
let columnGroup = this.columnGroup;
|
||||
|
||||
if (columnGroup.children && columnGroup.children.default) {
|
||||
for (let child of columnGroup.children.default()) {
|
||||
if (child.type.name === 'Row') {
|
||||
rows.push(child);
|
||||
}
|
||||
else if (child.children && child.children instanceof Array) {
|
||||
} else if (child.children && child.children instanceof Array) {
|
||||
rows = child.children;
|
||||
}
|
||||
}
|
||||
|
@ -153,15 +235,13 @@ export default {
|
|||
return rows;
|
||||
}
|
||||
},
|
||||
getHeaderColumns(row){
|
||||
getHeaderColumns(row) {
|
||||
let cols = [];
|
||||
|
||||
if (row.children && row.children.default) {
|
||||
row.children.default().forEach(child => {
|
||||
if (child.children && child.children instanceof Array)
|
||||
cols = [...cols, ...child.children];
|
||||
else if (child.type.name === 'Column')
|
||||
cols.push(child);
|
||||
row.children.default().forEach((child) => {
|
||||
if (child.children && child.children instanceof Array) cols = [...cols, ...child.children];
|
||||
else if (child.type.name === 'Column') cols.push(child);
|
||||
});
|
||||
|
||||
return cols;
|
||||
|
@ -169,9 +249,9 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
'DTHeaderCell': HeaderCell,
|
||||
'DTHeaderCheckbox': HeaderCheckbox,
|
||||
'DTColumnFilter': ColumnFilter
|
||||
DTHeaderCell: HeaderCell,
|
||||
DTHeaderCheckbox: HeaderCheckbox,
|
||||
DTColumnFilter: ColumnFilter
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<tbody class="p-datatable-tbody">
|
||||
<tr v-for="n in rows" :key="n">
|
||||
<td v-for="(col,i) of columns" :key="col.props.columnKey||col.props.field||i">
|
||||
<component :is="col.children.loading" :column="col" :index="i" v-if="col.children && col.children.loading" />
|
||||
<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>
|
||||
|
@ -21,5 +21,5 @@ export default {
|
|||
default: null
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -128,7 +128,7 @@ export interface DataViewSlots {
|
|||
* Custom footer template.
|
||||
*/
|
||||
footer: () => VNode[];
|
||||
/**
|
||||
/**
|
||||
* Custom empty template.
|
||||
*/
|
||||
empty: () => VNode[];
|
||||
|
@ -136,7 +136,7 @@ export interface DataViewSlots {
|
|||
* Custom paginator start template.
|
||||
*/
|
||||
paginatorstart: () => VNode[];
|
||||
/**
|
||||
/**
|
||||
* Custom paginator end template.
|
||||
*/
|
||||
paginatorend: () => VNode[];
|
||||
|
@ -176,7 +176,7 @@ export declare type DataViewEmits = {
|
|||
* @param {number} value - New value.
|
||||
*/
|
||||
'update:first': (value: number) => void;
|
||||
/**
|
||||
/**
|
||||
* Emitted when the rows changes.
|
||||
* @param {number} value - New value.
|
||||
*/
|
||||
|
@ -185,14 +185,14 @@ export declare type DataViewEmits = {
|
|||
* Callback to invoke when page changes, the event object contains information about the new state.
|
||||
* @param {DataViewPageEvent} event - Custom page event.
|
||||
*/
|
||||
'page': (event: DataViewPageEvent) => void;
|
||||
}
|
||||
page: (event: DataViewPageEvent) => void;
|
||||
};
|
||||
|
||||
declare class DataView extends ClassComponent<DataViewProps, DataViewSlots, DataViewEmits> { }
|
||||
declare class DataView extends ClassComponent<DataViewProps, DataViewSlots, DataViewEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
DataView: GlobalComponentConstructor<DataView>
|
||||
DataView: GlobalComponentConstructor<DataView>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [DataView](https://www.primefaces.org/primevue/showcase/#/dataview)
|
||||
* - [DataView](https://www.primefaces.org/primevue/dataview)
|
||||
*
|
||||
*/
|
||||
export default DataView;
|
||||
|
|
|
@ -7,44 +7,44 @@ describe('DataView.vue', () => {
|
|||
props: {
|
||||
value: [
|
||||
{
|
||||
"id": "1000",
|
||||
"code": "f230fh0g3",
|
||||
"name": "Bamboo Watch",
|
||||
"description": "Product Description",
|
||||
"image": "bamboo-watch.jpg",
|
||||
"price": 65,
|
||||
"category": "Accessories",
|
||||
"quantity": 24,
|
||||
"inventoryStatus": "INSTOCK",
|
||||
"rating": 5
|
||||
id: '1000',
|
||||
code: 'f230fh0g3',
|
||||
name: 'Bamboo Watch',
|
||||
description: 'Product Description',
|
||||
image: 'bamboo-watch.jpg',
|
||||
price: 65,
|
||||
category: 'Accessories',
|
||||
quantity: 24,
|
||||
inventoryStatus: 'INSTOCK',
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"code": "nvklal433",
|
||||
"name": "Black Watch",
|
||||
"description": "Product Description",
|
||||
"image": "black-watch.jpg",
|
||||
"price": 72,
|
||||
"category": "Accessories",
|
||||
"quantity": 61,
|
||||
"inventoryStatus": "INSTOCK",
|
||||
"rating": 4
|
||||
id: '1001',
|
||||
code: 'nvklal433',
|
||||
name: 'Black Watch',
|
||||
description: 'Product Description',
|
||||
image: 'black-watch.jpg',
|
||||
price: 72,
|
||||
category: 'Accessories',
|
||||
quantity: 61,
|
||||
inventoryStatus: 'INSTOCK',
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
"id": "1002",
|
||||
"code": "zz21cz3c1",
|
||||
"name": "Blue Band",
|
||||
"description": "Product Description",
|
||||
"image": "blue-band.jpg",
|
||||
"price": 79,
|
||||
"category": "Fitness",
|
||||
"quantity": 2,
|
||||
"inventoryStatus": "LOWSTOCK",
|
||||
"rating": 3
|
||||
id: '1002',
|
||||
code: 'zz21cz3c1',
|
||||
name: 'Blue Band',
|
||||
description: 'Product Description',
|
||||
image: 'blue-band.jpg',
|
||||
price: 79,
|
||||
category: 'Fitness',
|
||||
quantity: 2,
|
||||
inventoryStatus: 'LOWSTOCK',
|
||||
rating: 3
|
||||
}
|
||||
],
|
||||
layout: 'grid',
|
||||
paginator: true,
|
||||
paginator: true,
|
||||
rows: 3
|
||||
},
|
||||
slots: {
|
||||
|
|
|
@ -1,46 +1,68 @@
|
|||
<template>
|
||||
<div :class="containerClass">
|
||||
<div class="p-dataview-header" v-if="$slots.header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<DVPaginator v-if="paginatorTop" :rows="d_rows" :first="d_first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
|
||||
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}" :alwaysShow="alwaysShowPaginator" @page="onPage($event)">
|
||||
<template #start v-if="$slots.paginatorstart">
|
||||
<slot name="paginatorstart"></slot>
|
||||
</template>
|
||||
<template #end v-if="$slots.paginatorend">
|
||||
<slot name="paginatorend"></slot>
|
||||
</template>
|
||||
</DVPaginator>
|
||||
<div class="p-dataview-content">
|
||||
<div class="p-grid p-nogutter grid grid-nogutter">
|
||||
<template v-for="(item,index) of items" :key="getKey(item, index)">
|
||||
<slot v-if="$slots.list && layout === 'list'" name="list" :data="item" :index="index"></slot>
|
||||
<slot v-if="$slots.grid && layout === 'grid'" name="grid" :data="item" :index="index"></slot>
|
||||
</template>
|
||||
<div v-if="empty" class="p-col col">
|
||||
<div :class="containerClass">
|
||||
<div v-if="$slots.header" class="p-dataview-header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<DVPaginator
|
||||
v-if="paginatorTop"
|
||||
:rows="d_rows"
|
||||
:first="d_first"
|
||||
:totalRecords="getTotalRecords"
|
||||
:pageLinkSize="pageLinkSize"
|
||||
:template="paginatorTemplate"
|
||||
:rowsPerPageOptions="rowsPerPageOptions"
|
||||
:currentPageReportTemplate="currentPageReportTemplate"
|
||||
:class="{ 'p-paginator-top': paginatorTop }"
|
||||
:alwaysShow="alwaysShowPaginator"
|
||||
@page="onPage($event)"
|
||||
>
|
||||
<template v-if="$slots.paginatorstart" #start>
|
||||
<slot name="paginatorstart"></slot>
|
||||
</template>
|
||||
<template v-if="$slots.paginatorend" #end>
|
||||
<slot name="paginatorend"></slot>
|
||||
</template>
|
||||
</DVPaginator>
|
||||
<div class="p-dataview-content">
|
||||
<div class="p-grid p-nogutter grid grid-nogutter">
|
||||
<template v-for="(item, index) of items" :key="getKey(item, index)">
|
||||
<slot v-if="$slots.list && layout === 'list'" name="list" :data="item" :index="index"></slot>
|
||||
<slot v-if="$slots.grid && layout === 'grid'" name="grid" :data="item" :index="index"></slot>
|
||||
</template>
|
||||
<div v-if="empty" class="p-col col">
|
||||
<div class="p-dataview-emptymessage">
|
||||
<slot name="empty"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DVPaginator v-if="paginatorBottom" :rows="d_rows" :first="d_first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
|
||||
:currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}" :alwaysShow="alwaysShowPaginator" @page="onPage($event)">
|
||||
<template #start v-if="$slots.paginatorstart">
|
||||
<slot name="paginatorstart"></slot>
|
||||
</template>
|
||||
<template #end v-if="$slots.paginatorend">
|
||||
<slot name="paginatorend"></slot>
|
||||
</template>
|
||||
</DVPaginator>
|
||||
<div class="p-dataview-footer" v-if="$slots.footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DVPaginator
|
||||
v-if="paginatorBottom"
|
||||
:rows="d_rows"
|
||||
:first="d_first"
|
||||
:totalRecords="getTotalRecords"
|
||||
:pageLinkSize="pageLinkSize"
|
||||
:template="paginatorTemplate"
|
||||
:rowsPerPageOptions="rowsPerPageOptions"
|
||||
:currentPageReportTemplate="currentPageReportTemplate"
|
||||
:class="{ 'p-paginator-bottom': paginatorBottom }"
|
||||
:alwaysShow="alwaysShowPaginator"
|
||||
@page="onPage($event)"
|
||||
>
|
||||
<template v-if="$slots.paginatorstart" #start>
|
||||
<slot name="paginatorstart"></slot>
|
||||
</template>
|
||||
<template v-if="$slots.paginatorend" #end>
|
||||
<slot name="paginatorend"></slot>
|
||||
</template>
|
||||
</DVPaginator>
|
||||
<div v-if="$slots.footer" class="p-dataview-footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {ObjectUtils} from 'primevue/utils';
|
||||
import { ObjectUtils } from 'primevue/utils';
|
||||
import Paginator from 'primevue/paginator';
|
||||
|
||||
export default {
|
||||
|
@ -116,7 +138,7 @@ export default {
|
|||
return {
|
||||
d_first: this.first,
|
||||
d_rows: this.rows
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
first(newValue) {
|
||||
|
@ -153,23 +175,17 @@ export default {
|
|||
let value2 = ObjectUtils.resolveFieldData(data2, this.sortField);
|
||||
let result = null;
|
||||
|
||||
if (value1 == null && value2 != null)
|
||||
result = -1;
|
||||
else if (value1 != null && value2 == null)
|
||||
result = 1;
|
||||
else if (value1 == null && value2 == null)
|
||||
result = 0;
|
||||
else if (typeof value1 === 'string' && typeof value2 === 'string')
|
||||
result = value1.localeCompare(value2, undefined, { numeric: true });
|
||||
else
|
||||
result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
|
||||
if (value1 == null && value2 != null) result = -1;
|
||||
else if (value1 != null && value2 == null) result = 1;
|
||||
else if (value1 == null && value2 == null) result = 0;
|
||||
else if (typeof value1 === 'string' && typeof value2 === 'string') result = value1.localeCompare(value2, undefined, { numeric: true });
|
||||
else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
|
||||
|
||||
return (this.sortOrder * result);
|
||||
return this.sortOrder * result;
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
@ -180,20 +196,20 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-dataview p-component', {
|
||||
'p-dataview-list': (this.layout === 'list'),
|
||||
'p-dataview-grid': (this.layout === 'grid')
|
||||
return [
|
||||
'p-dataview p-component',
|
||||
{
|
||||
'p-dataview-list': this.layout === 'list',
|
||||
'p-dataview-grid': this.layout === 'grid'
|
||||
}
|
||||
]
|
||||
];
|
||||
},
|
||||
getTotalRecords() {
|
||||
if (this.totalRecords)
|
||||
return this.totalRecords;
|
||||
else
|
||||
return this.value ? this.value.length : 0;
|
||||
if (this.totalRecords) return this.totalRecords;
|
||||
else return this.value ? this.value.length : 0;
|
||||
},
|
||||
empty() {
|
||||
return (!this.value || this.value.length === 0);
|
||||
return !this.value || this.value.length === 0;
|
||||
},
|
||||
paginatorTop() {
|
||||
return this.paginator && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both');
|
||||
|
@ -211,20 +227,18 @@ export default {
|
|||
|
||||
if (this.paginator) {
|
||||
const first = this.lazy ? 0 : this.d_first;
|
||||
|
||||
return data.slice(first, first + this.d_rows);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'DVPaginator': Paginator
|
||||
DVPaginator: Paginator
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -7,8 +7,7 @@ export interface DataViewLayoutOptionsProps {
|
|||
modelValue?: string | undefined;
|
||||
}
|
||||
|
||||
export interface DataViewLayoutOptionsSlots {
|
||||
}
|
||||
export interface DataViewLayoutOptionsSlots {}
|
||||
|
||||
export declare type DataViewLayoutOptionsEmits = {
|
||||
/**
|
||||
|
@ -16,13 +15,13 @@ export declare type DataViewLayoutOptionsEmits = {
|
|||
* @param {*} value - New value.
|
||||
*/
|
||||
'update:modelValue': (value: string) => void;
|
||||
}
|
||||
};
|
||||
|
||||
declare class DataViewLayoutOptions extends ClassComponent<DataViewLayoutOptionsProps, DataViewLayoutOptionsSlots, DataViewLayoutOptionsEmits> { }
|
||||
declare class DataViewLayoutOptions extends ClassComponent<DataViewLayoutOptionsProps, DataViewLayoutOptionsSlots, DataViewLayoutOptionsEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
DataViewLayoutOptions: GlobalComponentConstructor<DataViewLayoutOptions>
|
||||
DataViewLayoutOptions: GlobalComponentConstructor<DataViewLayoutOptions>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +32,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [DataViewLayoutOptions](https://www.primefaces.org/primevue/showcase/#/dataview)
|
||||
* - [DataViewLayoutOptions](https://www.primefaces.org/primevue/dataview)
|
||||
*
|
||||
*/
|
||||
export default DataViewLayoutOptions;
|
||||
|
|
|
@ -1,39 +1,33 @@
|
|||
<template>
|
||||
<div class="p-dataview-layout-options p-selectbutton p-buttonset">
|
||||
<button :class="buttonListClass" @click="changeLayout('list')" type="button">
|
||||
<i class="pi pi-bars"></i>
|
||||
</button>
|
||||
<button :class="buttonGridClass" @click="changeLayout('grid')" type="button">
|
||||
<i class="pi pi-th-large"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="p-dataview-layout-options p-selectbutton p-buttonset">
|
||||
<button :class="buttonListClass" @click="changeLayout('list')" type="button">
|
||||
<i class="pi pi-bars"></i>
|
||||
</button>
|
||||
<button :class="buttonGridClass" @click="changeLayout('grid')" type="button">
|
||||
<i class="pi pi-th-large"></i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DataViewLayoutOptions',
|
||||
emits: ['update:modelValue'],
|
||||
props: {
|
||||
modelValue: String
|
||||
},
|
||||
computed: {
|
||||
buttonListClass(){
|
||||
return [
|
||||
'p-button p-button-icon-only',
|
||||
{'p-highlight': this.modelValue === 'list'}
|
||||
]
|
||||
},
|
||||
buttonGridClass() {
|
||||
return [
|
||||
'p-button p-button-icon-only',
|
||||
{'p-highlight': this.modelValue === 'grid'}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeLayout(layout){
|
||||
this.$emit('update:modelValue', layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'DataViewLayoutOptions',
|
||||
emits: ['update:modelValue'],
|
||||
props: {
|
||||
modelValue: String
|
||||
},
|
||||
methods: {
|
||||
changeLayout(layout) {
|
||||
this.$emit('update:modelValue', layout);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
buttonListClass() {
|
||||
return ['p-button p-button-icon-only', { 'p-highlight': this.modelValue === 'list' }];
|
||||
},
|
||||
buttonGridClass() {
|
||||
return ['p-button p-button-icon-only', { 'p-highlight': this.modelValue === 'grid' }];
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
export interface DeferredContentProps {
|
||||
}
|
||||
export interface DeferredContentProps {}
|
||||
|
||||
export interface DeferredContentSlots {
|
||||
/**
|
||||
|
@ -15,14 +14,14 @@ export declare type DeferredContentEmits = {
|
|||
/**
|
||||
* Callback to invoke when deferred content is loaded.
|
||||
*/
|
||||
'load': () => void;
|
||||
}
|
||||
load: () => void;
|
||||
};
|
||||
|
||||
declare class DeferredContent extends ClassComponent<DeferredContentProps, DeferredContentSlots, DeferredContentEmits> { }
|
||||
declare class DeferredContent extends ClassComponent<DeferredContentProps, DeferredContentSlots, DeferredContentEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
DeferredContent: GlobalComponentConstructor<DeferredContent>
|
||||
DeferredContent: GlobalComponentConstructor<DeferredContent>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +31,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [DeferredContent](https://www.primefaces.org/primevue/showcase/#/deferredcontent)
|
||||
* - [DeferredContent](https://www.primefaces.org/primevue/deferredcontent)
|
||||
*
|
||||
*/
|
||||
export default DeferredContent;
|
||||
|
|
|
@ -11,14 +11,12 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
loaded: false
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (!this.loaded) {
|
||||
if (this.shouldLoad())
|
||||
this.load();
|
||||
else
|
||||
this.bindScrollListener();
|
||||
if (this.shouldLoad()) this.load();
|
||||
else this.bindScrollListener();
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
|
@ -44,13 +42,12 @@ export default {
|
|||
shouldLoad() {
|
||||
if (this.loaded) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const rect = this.$refs.container.getBoundingClientRect();
|
||||
const docElement = document.documentElement;
|
||||
const winHeight = docElement.clientHeight;
|
||||
|
||||
return (winHeight >= rect.top);
|
||||
return winHeight >= rect.top;
|
||||
}
|
||||
},
|
||||
load(event) {
|
||||
|
@ -58,5 +55,5 @@ export default {
|
|||
this.$emit('load', event);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -158,37 +158,37 @@ export declare type DialogEmits = {
|
|||
/**
|
||||
* Callback to invoke when dialog is hidden.
|
||||
*/
|
||||
'hide': () => void;
|
||||
hide: () => void;
|
||||
/**
|
||||
* Callback to invoke after dialog is hidden.
|
||||
*/
|
||||
*/
|
||||
'after-hide': () => void;
|
||||
/**
|
||||
* Callback to invoke when dialog is shown.
|
||||
*/
|
||||
'show': () => void;
|
||||
show: () => void;
|
||||
/**
|
||||
* Fired when a dialog gets maximized.
|
||||
* @param {event} event - Browser event.
|
||||
*/
|
||||
'maximize': (event: Event) => void;
|
||||
maximize: (event: Event) => void;
|
||||
/**
|
||||
* Fired when a dialog gets unmaximized.
|
||||
* @param {event} event - Browser event.
|
||||
*/
|
||||
'unmaximize': (event: Event) => void;
|
||||
unmaximize: (event: Event) => void;
|
||||
/**
|
||||
* Fired when a dialog drag completes.
|
||||
* @param {event} event - Browser event.
|
||||
*/
|
||||
'dragend': (event: Event) => void;
|
||||
}
|
||||
dragend: (event: Event) => void;
|
||||
};
|
||||
|
||||
declare class Dialog extends ClassComponent<DialogProps, DialogSlots, DialogEmits> { }
|
||||
declare class Dialog extends ClassComponent<DialogProps, DialogSlots, DialogEmits> {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Dialog: GlobalComponentConstructor<Dialog>
|
||||
Dialog: GlobalComponentConstructor<Dialog>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ declare module '@vue/runtime-core' {
|
|||
*
|
||||
* Demos:
|
||||
*
|
||||
* - [Dialog](https://www.primefaces.org/primevue/showcase/#/dialog)
|
||||
* - [Dialog](https://www.primefaces.org/primevue/dialog)
|
||||
*
|
||||
*/
|
||||
export default Dialog;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import PrimeVue from '@/components/config/PrimeVue';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import Dialog from './Dialog.vue';
|
||||
|
||||
describe('Dialog.vue', () => {
|
||||
it('is Dialog element exist', async() => {
|
||||
const wrapper = mount(Dialog, {
|
||||
global: {
|
||||
it('is Dialog element exist', async () => {
|
||||
const wrapper = mount(Dialog, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true
|
||||
|
@ -14,18 +14,18 @@ describe('Dialog.vue', () => {
|
|||
props: {
|
||||
visible: false
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-dialog.p-component').exists()).toBe(false);
|
||||
expect(wrapper.find('.p-dialog.p-component').exists()).toBe(false);
|
||||
|
||||
await wrapper.setProps({ visible: true });
|
||||
await wrapper.setProps({ visible: true });
|
||||
|
||||
expect(wrapper.find('.p-dialog.p-component').exists()).toBe(true);
|
||||
});
|
||||
expect(wrapper.find('.p-dialog.p-component').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('slot checks', async() => {
|
||||
const wrapper = mount(Dialog, {
|
||||
global: {
|
||||
it('slot checks', async () => {
|
||||
const wrapper = mount(Dialog, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true
|
||||
|
@ -34,13 +34,13 @@ describe('Dialog.vue', () => {
|
|||
props: {
|
||||
visible: true
|
||||
},
|
||||
slots: {
|
||||
default: '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit</p>',
|
||||
footer: '<p>Dialog Footer</p>'
|
||||
}
|
||||
});
|
||||
slots: {
|
||||
default: '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit</p>',
|
||||
footer: '<p>Dialog Footer</p>'
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-dialog-content').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-dialog-footer').exists()).toBe(true);
|
||||
});
|
||||
expect(wrapper.find('.p-dialog-content').exists()).toBe(false);
|
||||
expect(wrapper.find('.p-dialog-footer').exists()).toBe(false);
|
||||
});
|
||||
});
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<Portal :appendTo="appendTo">
|
||||
<div :ref="maskRef" :class="maskClass" v-if="containerVisible" @click="onMaskClick">
|
||||
<div v-if="containerVisible" :ref="maskRef" :class="maskClass" @click="onMaskClick">
|
||||
<transition name="p-dialog" @before-enter="onBeforeEnter" @enter="onEnter" @before-leave="onBeforeLeave" @leave="onLeave" @after-leave="onAfterLeave" appear>
|
||||
<div :ref="containerRef" :class="dialogClass" v-if="visible" v-bind="$attrs" role="dialog" :aria-labelledby="ariaLabelledById" :aria-modal="modal">
|
||||
<div class="p-dialog-header" v-if="showHeader" @mousedown="initDrag">
|
||||
<div v-if="visible" :ref="containerRef" :class="dialogClass" v-bind="$attrs" role="dialog" :aria-labelledby="ariaLabelledById" :aria-modal="modal">
|
||||
<div v-if="showHeader" class="p-dialog-header" @mousedown="initDrag">
|
||||
<slot name="header">
|
||||
<span :id="ariaLabelledById" class="p-dialog-title" v-if="header">{{header}}</span>
|
||||
<span v-if="header" :id="ariaLabelledById" class="p-dialog-title">{{ header }}</span>
|
||||
</slot>
|
||||
<div class="p-dialog-header-icons">
|
||||
<button class="p-dialog-header-icon p-dialog-header-maximize p-link" @click="maximize" v-if="maximizable" type="button" tabindex="-1" v-ripple>
|
||||
<button v-if="maximizable" v-ripple class="p-dialog-header-icon p-dialog-header-maximize p-link" @click="maximize" type="button" tabindex="-1">
|
||||
<span :class="maximizeIconClass"></span>
|
||||
</button>
|
||||
<button class="p-dialog-header-icon p-dialog-header-close p-link" @click="close" v-if="closable" :aria-label="ariaCloseLabel" type="button" v-ripple>
|
||||
<button v-if="closable" v-ripple class="p-dialog-header-icon p-dialog-header-close p-link" @click="close" :aria-label="ariaCloseLabel" type="button">
|
||||
<span class="p-dialog-header-close-icon pi pi-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -19,8 +19,8 @@
|
|||
<div :class="contentStyleClass" :style="contentStyle">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="p-dialog-footer" v-if="footer || $slots.footer">
|
||||
<slot name="footer">{{footer}}</slot>
|
||||
<div v-if="footer || $slots.footer" class="p-dialog-footer">
|
||||
<slot name="footer">{{ footer }}</slot>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
@ -30,14 +30,14 @@
|
|||
|
||||
<script>
|
||||
import { computed } from 'vue';
|
||||
import { UniqueComponentId,DomHandler,ZIndexUtils } from 'primevue/utils';
|
||||
import { UniqueComponentId, DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
import Ripple from 'primevue/ripple';
|
||||
import Portal from 'primevue/portal';
|
||||
|
||||
export default {
|
||||
name: 'Dialog',
|
||||
inheritAttrs: false,
|
||||
emits: ['update:visible','show','hide', 'after-hide', 'maximize','unmaximize','dragend'],
|
||||
emits: ['update:visible', 'show', 'hide', 'after-hide', 'maximize', 'unmaximize', 'dragend'],
|
||||
props: {
|
||||
header: null,
|
||||
footer: null,
|
||||
|
@ -105,13 +105,13 @@ export default {
|
|||
provide() {
|
||||
return {
|
||||
dialogRef: computed(() => this._instance)
|
||||
}
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
containerVisible: this.visible,
|
||||
maximized: false
|
||||
}
|
||||
};
|
||||
},
|
||||
documentKeydownListener: null,
|
||||
container: null,
|
||||
|
@ -135,6 +135,7 @@ export default {
|
|||
if (this.mask && this.autoZIndex) {
|
||||
ZIndexUtils.clear(this.mask);
|
||||
}
|
||||
|
||||
this.container = null;
|
||||
this.mask = null;
|
||||
},
|
||||
|
@ -172,6 +173,7 @@ export default {
|
|||
if (this.autoZIndex) {
|
||||
ZIndexUtils.clear(this.mask);
|
||||
}
|
||||
|
||||
this.containerVisible = false;
|
||||
this.unbindDocumentState();
|
||||
this.unbindGlobalListeners();
|
||||
|
@ -184,6 +186,7 @@ export default {
|
|||
},
|
||||
focus() {
|
||||
let focusTarget = this.container.querySelector('[autofocus]');
|
||||
|
||||
if (focusTarget) {
|
||||
focusTarget.focus();
|
||||
}
|
||||
|
@ -192,17 +195,14 @@ export default {
|
|||
if (this.maximized) {
|
||||
this.maximized = false;
|
||||
this.$emit('unmaximize', event);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.maximized = true;
|
||||
this.$emit('maximize', event);
|
||||
}
|
||||
|
||||
if (!this.modal) {
|
||||
if (this.maximized)
|
||||
DomHandler.addClass(document.body, 'p-overflow-hidden');
|
||||
else
|
||||
DomHandler.removeClass(document.body, 'p-overflow-hidden');
|
||||
if (this.maximized) DomHandler.addClass(document.body, 'p-overflow-hidden');
|
||||
else DomHandler.removeClass(document.body, 'p-overflow-hidden');
|
||||
}
|
||||
},
|
||||
enableDocumentSettings() {
|
||||
|
@ -219,23 +219,19 @@ export default {
|
|||
if (event.which === 9) {
|
||||
event.preventDefault();
|
||||
let focusableElements = DomHandler.getFocusableElements(this.container);
|
||||
|
||||
if (focusableElements && focusableElements.length > 0) {
|
||||
if (!document.activeElement) {
|
||||
focusableElements[0].focus();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let focusedIndex = focusableElements.indexOf(document.activeElement);
|
||||
|
||||
if (event.shiftKey) {
|
||||
if (focusedIndex == -1 || focusedIndex === 0)
|
||||
focusableElements[focusableElements.length - 1].focus();
|
||||
else
|
||||
focusableElements[focusedIndex - 1].focus();
|
||||
}
|
||||
else {
|
||||
if (focusedIndex == -1 || focusedIndex === (focusableElements.length - 1))
|
||||
focusableElements[0].focus();
|
||||
else
|
||||
focusableElements[focusedIndex + 1].focus();
|
||||
if (focusedIndex == -1 || focusedIndex === 0) focusableElements[focusableElements.length - 1].focus();
|
||||
else focusableElements[focusedIndex - 1].focus();
|
||||
} else {
|
||||
if (focusedIndex == -1 || focusedIndex === focusableElements.length - 1) focusableElements[0].focus();
|
||||
else focusableElements[focusedIndex + 1].focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +253,7 @@ export default {
|
|||
},
|
||||
getPositionClass() {
|
||||
const positions = ['left', 'right', 'top', 'topleft', 'topright', 'bottom', 'bottomleft', 'bottomright'];
|
||||
const pos = positions.find(item => item === this.position);
|
||||
const pos = positions.find((item) => item === this.position);
|
||||
|
||||
return pos ? `p-dialog-${pos}` : '';
|
||||
},
|
||||
|
@ -268,12 +264,13 @@ export default {
|
|||
this.mask = el;
|
||||
},
|
||||
createStyle() {
|
||||
if (!this.styleElement) {
|
||||
this.styleElement = document.createElement('style');
|
||||
this.styleElement.type = 'text/css';
|
||||
document.head.appendChild(this.styleElement);
|
||||
if (!this.styleElement) {
|
||||
this.styleElement = document.createElement('style');
|
||||
this.styleElement.type = 'text/css';
|
||||
document.head.appendChild(this.styleElement);
|
||||
|
||||
let innerHTML = '';
|
||||
|
||||
for (let breakpoint in this.breakpoints) {
|
||||
innerHTML += `
|
||||
@media screen and (max-width: ${breakpoint}) {
|
||||
|
@ -281,12 +278,12 @@ export default {
|
|||
width: ${this.breakpoints[breakpoint]} !important;
|
||||
}
|
||||
}
|
||||
`
|
||||
`;
|
||||
}
|
||||
|
||||
this.styleElement.innerHTML = innerHTML;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
destroyStyle() {
|
||||
if (this.styleElement) {
|
||||
document.head.removeChild(this.styleElement);
|
||||
|
@ -337,24 +334,24 @@ export default {
|
|||
this.container.style.position = 'fixed';
|
||||
|
||||
if (this.keepInViewport) {
|
||||
if (leftPos >= this.minX && (leftPos + width) < viewport.width) {
|
||||
if (leftPos >= this.minX && leftPos + width < viewport.width) {
|
||||
this.lastPageX = event.pageX;
|
||||
this.container.style.left = leftPos + 'px';
|
||||
}
|
||||
|
||||
if (topPos >= this.minY && (topPos + height) < viewport.height) {
|
||||
if (topPos >= this.minY && topPos + height < viewport.height) {
|
||||
this.lastPageY = event.pageY;
|
||||
this.container.style.top = topPos + 'px';
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.lastPageX = event.pageX;
|
||||
this.container.style.left = leftPos + 'px';
|
||||
this.lastPageY = event.pageY;
|
||||
this.container.style.top = topPos + 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.document.addEventListener('mousemove', this.documentDragListener);
|
||||
},
|
||||
unbindDocumentDragListener() {
|
||||
|
@ -372,6 +369,7 @@ export default {
|
|||
this.$emit('dragend', event);
|
||||
}
|
||||
};
|
||||
|
||||
window.document.addEventListener('mouseup', this.documentDragEndListener);
|
||||
},
|
||||
unbindDocumentDragEndListener() {
|
||||
|
@ -383,21 +381,27 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
maskClass() {
|
||||
return ['p-dialog-mask', {'p-component-overlay p-component-overlay-enter': this.modal}, this.getPositionClass()];
|
||||
return ['p-dialog-mask', { 'p-component-overlay p-component-overlay-enter': this.modal }, this.getPositionClass()];
|
||||
},
|
||||
dialogClass() {
|
||||
return ['p-dialog p-component', {
|
||||
'p-dialog-rtl': this.rtl,
|
||||
'p-dialog-maximized': this.maximizable && this.maximized,
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}];
|
||||
return [
|
||||
'p-dialog p-component',
|
||||
{
|
||||
'p-dialog-rtl': this.rtl,
|
||||
'p-dialog-maximized': this.maximizable && this.maximized,
|
||||
'p-input-filled': this.$primevue.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': this.$primevue.config.ripple === false
|
||||
}
|
||||
];
|
||||
},
|
||||
maximizeIconClass() {
|
||||
return ['p-dialog-header-maximize-icon pi', {
|
||||
'pi-window-maximize': !this.maximized,
|
||||
'pi-window-minimize': this.maximized
|
||||
}];
|
||||
return [
|
||||
'p-dialog-header-maximize-icon pi',
|
||||
{
|
||||
'pi-window-maximize': !this.maximized,
|
||||
'pi-window-minimize': this.maximized
|
||||
}
|
||||
];
|
||||
},
|
||||
ariaId() {
|
||||
return UniqueComponentId();
|
||||
|
@ -413,12 +417,12 @@ export default {
|
|||
}
|
||||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
ripple: Ripple
|
||||
},
|
||||
components: {
|
||||
'Portal': Portal
|
||||
Portal: Portal
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.p-dialog-mask {
|
||||
|
@ -484,7 +488,7 @@ export default {
|
|||
transition: all 150ms cubic-bezier(0, 0, 0.2, 1);
|
||||
}
|
||||
.p-dialog-leave-active {
|
||||
transition: all 150ms cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.p-dialog-enter-from,
|
||||
.p-dialog-leave-to {
|
||||
|
@ -501,7 +505,7 @@ export default {
|
|||
.p-dialog-topright .p-dialog,
|
||||
.p-dialog-bottomleft .p-dialog,
|
||||
.p-dialog-bottomright .p-dialog {
|
||||
margin: .75rem;
|
||||
margin: 0.75rem;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
.p-dialog-top .p-dialog-enter-active,
|
||||
|
@ -520,7 +524,7 @@ export default {
|
|||
.p-dialog-bottomleft .p-dialog-leave-active,
|
||||
.p-dialog-bottomright .p-dialog-enter-active,
|
||||
.p-dialog-bottomright .p-dialog-leave-active {
|
||||
transition: all .3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
.p-dialog-top .p-dialog-enter-from,
|
||||
.p-dialog-top .p-dialog-leave-to {
|
||||
|
|
|
@ -13,7 +13,7 @@ export default {
|
|||
close: (params) => {
|
||||
DynamicDialogEventBus.emit('close', { instance, params });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DynamicDialogEventBus.emit('open', { instance });
|
||||
|
||||
|
@ -25,4 +25,4 @@ export default {
|
|||
app.config.globalProperties.$dialog = DialogService;
|
||||
app.provide(PrimeVueDialogSymbol, DialogService);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue