primeng
Version:
[](https://badge.fury.io/js/primeng) [](https://www.npmjs.com/package/primeng) [ • 102 kB
JavaScript
import * as i5 from '@angular/cdk/drag-drop';
import { transferArrayItem, moveItemInArray, DragDropModule, CDK_DRAG_CONFIG } from '@angular/cdk/drag-drop';
import * as i2 from '@angular/common';
import { isPlatformBrowser, DOCUMENT, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { EventEmitter, PLATFORM_ID, numberAttribute, booleanAttribute, Component, ChangeDetectionStrategy, ViewEncapsulation, Inject, Input, Output, ViewChild, ContentChildren, NgModule } from '@angular/core';
import * as i1 from 'primeng/api';
import { PrimeTemplate, SharedModule } from 'primeng/api';
import * as i3 from 'primeng/button';
import { ButtonModule } from 'primeng/button';
import { DomHandler } from 'primeng/dom';
import { AngleDoubleDownIcon } from 'primeng/icons/angledoubledown';
import { AngleDoubleLeftIcon } from 'primeng/icons/angledoubleleft';
import { AngleDoubleRightIcon } from 'primeng/icons/angledoubleright';
import { AngleDoubleUpIcon } from 'primeng/icons/angledoubleup';
import { AngleDownIcon } from 'primeng/icons/angledown';
import { AngleLeftIcon } from 'primeng/icons/angleleft';
import { AngleRightIcon } from 'primeng/icons/angleright';
import { AngleUpIcon } from 'primeng/icons/angleup';
import { HomeIcon } from 'primeng/icons/home';
import { SearchIcon } from 'primeng/icons/search';
import * as i4 from 'primeng/ripple';
import { RippleModule } from 'primeng/ripple';
import { UniqueComponentId, ObjectUtils } from 'primeng/utils';
/**
* PickList is used to reorder items between different lists.
* @group Components
*/
class PickList {
document;
platformId;
renderer;
el;
cd;
filterService;
config;
/**
* An array of objects for the source list.
* @group Props
*/
source;
/**
* An array of objects for the target list.
* @group Props
*/
target;
/**
* Text for the source list caption
* @group Props
*/
sourceHeader;
/**
* Index of the element in tabbing order.
* @group Props
*/
tabindex = 0;
/**
* Defines a string that labels the move to right button for accessibility.
* @group Props
*/
rightButtonAriaLabel;
/**
* Defines a string that labels the move to left button for accessibility.
* @group Props
*/
leftButtonAriaLabel;
/**
* Defines a string that labels the move to all right button for accessibility.
* @group Props
*/
allRightButtonAriaLabel;
/**
* Defines a string that labels the move to all left button for accessibility.
* @group Props
*/
allLeftButtonAriaLabel;
/**
* Defines a string that labels the move to up button for accessibility.
* @group Props
*/
upButtonAriaLabel;
/**
* Defines a string that labels the move to down button for accessibility.
* @group Props
*/
downButtonAriaLabel;
/**
* Defines a string that labels the move to top button for accessibility.
* @group Props
*/
topButtonAriaLabel;
/**
* Defines a string that labels the move to bottom button for accessibility.
* @group Props
*/
bottomButtonAriaLabel;
/**
* Text for the target list caption
* @group Props
*/
targetHeader;
/**
* When enabled orderlist adjusts its controls based on screen size.
* @group Props
*/
responsive;
/**
* When specified displays an input field to filter the items on keyup and decides which field to search (Accepts multiple fields with a comma).
* @group Props
*/
filterBy;
/**
* Locale to use in filtering. The default locale is the host environment's current locale.
* @group Props
*/
filterLocale;
/**
* Function to optimize the dom operations by delegating to ngForTrackBy, default algorithm checks for object identity. Use sourceTrackBy or targetTrackBy in case different algorithms are needed per list.
* @group Props
*/
trackBy = (index, item) => item;
/**
* Function to optimize the dom operations by delegating to ngForTrackBy in source list, default algorithm checks for object identity.
* @group Props
*/
sourceTrackBy;
/**
* Function to optimize the dom operations by delegating to ngForTrackBy in target list, default algorithm checks for object identity.
* @group Props
*/
targetTrackBy;
/**
* Whether to show filter input for source list when filterBy is enabled.
* @group Props
*/
showSourceFilter = true;
/**
* Whether to show filter input for target list when filterBy is enabled.
* @group Props
*/
showTargetFilter = true;
/**
* Defines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
* @group Props
*/
metaKeySelection = false;
/**
* Whether to enable dragdrop based reordering.
* @group Props
*/
dragdrop = false;
/**
* Inline style of the component.
* @group Props
*/
style;
/**
* Style class of the component.
* @group Props
*/
styleClass;
/**
* Inline style of the source list element.
* @group Props
*/
sourceStyle;
/**
* Inline style of the target list element.
* @group Props
*/
targetStyle;
/**
* Whether to show buttons of source list.
* @group Props
*/
showSourceControls = true;
/**
* Whether to show buttons of target list.
* @group Props
*/
showTargetControls = true;
/**
* Placeholder text on source filter input.
* @group Props
*/
sourceFilterPlaceholder;
/**
* Placeholder text on target filter input.
* @group Props
*/
targetFilterPlaceholder;
/**
* When present, it specifies that the component should be disabled.
* @group Props
*/
disabled = false;
/**
* Defines a string that labels the filter input of source list.
* @group Props
*/
ariaSourceFilterLabel;
/**
* Defines a string that labels the filter input of target list.
* @group Props
*/
ariaTargetFilterLabel;
/**
* Defines how the items are filtered.
* @group Props
*/
filterMatchMode = 'contains';
/**
* Whether to displays rows with alternating colors.
* @group Props
*/
stripedRows;
/**
* Keeps selection on the transfer list.
* @group Props
*/
keepSelection = false;
/**
* Indicates the width of the screen at which the component should change its behavior.
* @group Props
*/
get breakpoint() {
return this._breakpoint;
}
set breakpoint(value) {
if (value !== this._breakpoint) {
this._breakpoint = value;
if (isPlatformBrowser(this.platformId)) {
this.destroyMedia();
this.initMedia();
}
}
}
/**
* Callback to invoke when items are moved from target to source.
* @param {PickListMoveToSourceEvent} event - Custom move to source event.
* @group Emits
*/
onMoveToSource = new EventEmitter();
/**
* Callback to invoke when all items are moved from target to source.
* @param {PickListMoveAllToSourceEvent} event - Custom move all to source event.
* @group Emits
*/
onMoveAllToSource = new EventEmitter();
/**
* Callback to invoke when all items are moved from source to target.
* @param {PickListMoveAllToTargetEvent} event - Custom move all to target event.
* @group Emits
*/
onMoveAllToTarget = new EventEmitter();
/**
* Callback to invoke when items are moved from source to target.
* @param {PickListMoveToTargetEvent} event - Custom move to target event.
* @group Emits
*/
onMoveToTarget = new EventEmitter();
/**
* Callback to invoke when items are reordered within source list.
* @param {PickListSourceReorderEvent} event - Custom source reorder event.
* @group Emits
*/
onSourceReorder = new EventEmitter();
/**
* Callback to invoke when items are reordered within target list.
* @param {PickListTargetReorderEvent} event - Custom target reorder event.
* @group Emits
*/
onTargetReorder = new EventEmitter();
/**
* Callback to invoke when items are selected within source list.
* @param {PickListSourceSelectEvent} event - Custom source select event.
* @group Emits
*/
onSourceSelect = new EventEmitter();
/**
* Callback to invoke when items are selected within target list.
* @param {PickListTargetSelectEvent} event - Custom target select event.
* @group Emits
*/
onTargetSelect = new EventEmitter();
/**
* Callback to invoke when the source list is filtered
* @param {PickListSourceFilterEvent} event - Custom source filter event.
* @group Emits
*/
onSourceFilter = new EventEmitter();
/**
* Callback to invoke when the target list is filtered
* @param {PickListTargetFilterEvent} event - Custom target filter event.
* @group Emits
*/
onTargetFilter = new EventEmitter();
/**
* Callback to invoke when the list is focused
* @param {Event} event - Browser event.
* @group Emits
*/
onFocus = new EventEmitter();
/**
* Callback to invoke when the list is blurred
* @param {Event} event - Browser event.
* @group Emits
*/
onBlur = new EventEmitter();
listViewSourceChild;
listViewTargetChild;
sourceFilterViewChild;
targetFilterViewChild;
templates;
get moveUpAriaLabel() {
return this.upButtonAriaLabel ? this.upButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveUp : undefined;
}
get moveTopAriaLabel() {
return this.topButtonAriaLabel ? this.topButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveTop : undefined;
}
get moveDownAriaLabel() {
return this.downButtonAriaLabel ? this.downButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveDown : undefined;
}
get moveBottomAriaLabel() {
return this.bottomButtonAriaLabel ? this.bottomButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveDown : undefined;
}
get moveToTargetAriaLabel() {
return this.rightButtonAriaLabel ? this.rightButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveToTarget : undefined;
}
get moveAllToTargetAriaLabel() {
return this.allRightButtonAriaLabel ? this.allRightButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveAllToTarget : undefined;
}
get moveToSourceAriaLabel() {
return this.leftButtonAriaLabel ? this.leftButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveToSource : undefined;
}
get moveAllToSourceAriaLabel() {
return this.allLeftButtonAriaLabel ? this.allLeftButtonAriaLabel : this.config.translation.aria ? this.config.translation.aria.moveAllToSource : undefined;
}
get idSource() {
return this.id + '_source';
}
get idTarget() {
return this.id + '_target';
}
get focusedOptionId() {
return this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : null;
}
_breakpoint = '960px';
itemTemplate;
moveTopIconTemplate;
moveUpIconTemplate;
moveDownIconTemplate;
moveBottomIconTemplate;
moveToTargetIconTemplate;
moveAllToTargetIconTemplate;
moveToSourceIconTemplate;
moveAllToSourceIconTemplate;
targetFilterIconTemplate;
sourceFilterIconTemplate;
visibleOptionsSource;
visibleOptionsTarget;
selectedItemsSource = [];
selectedItemsTarget = [];
reorderedListElement;
movedUp;
movedDown;
itemTouched;
styleElement;
id = UniqueComponentId();
filterValueSource;
filterValueTarget;
fromListType;
emptyMessageSourceTemplate;
emptyFilterMessageSourceTemplate;
emptyMessageTargetTemplate;
emptyFilterMessageTargetTemplate;
sourceHeaderTemplate;
targetHeaderTemplate;
sourceFilterTemplate;
targetFilterTemplate;
sourceFilterOptions;
targetFilterOptions;
SOURCE_LIST = -1;
TARGET_LIST = 1;
window;
media;
viewChanged;
focusedOptionIndex = -1;
focusedOption;
focused = {
sourceList: false,
targetList: false
};
mediaChangeListener;
constructor(document, platformId, renderer, el, cd, filterService, config) {
this.document = document;
this.platformId = platformId;
this.renderer = renderer;
this.el = el;
this.cd = cd;
this.filterService = filterService;
this.config = config;
this.window = this.document.defaultView;
}
ngOnInit() {
if (this.responsive) {
this.createStyle();
this.initMedia();
}
if (this.filterBy) {
this.sourceFilterOptions = {
filter: (value) => this.filterSource(value),
reset: () => this.resetSourceFilter()
};
this.targetFilterOptions = {
filter: (value) => this.filterTarget(value),
reset: () => this.resetTargetFilter()
};
}
}
ngAfterContentInit() {
this.templates.forEach((item) => {
switch (item.getType()) {
case 'item':
this.itemTemplate = item.template;
break;
case 'sourceHeader':
this.sourceHeaderTemplate = item.template;
break;
case 'targetHeader':
this.targetHeaderTemplate = item.template;
break;
case 'sourceFilter':
this.sourceFilterTemplate = item.template;
break;
case 'targetFilter':
this.targetFilterTemplate = item.template;
break;
case 'emptymessagesource':
this.emptyMessageSourceTemplate = item.template;
break;
case 'emptyfiltermessagesource':
this.emptyFilterMessageSourceTemplate = item.template;
break;
case 'emptymessagetarget':
this.emptyMessageTargetTemplate = item.template;
break;
case 'emptyfiltermessagetarget':
this.emptyFilterMessageTargetTemplate = item.template;
break;
case 'moveupicon':
this.moveUpIconTemplate = item.template;
break;
case 'movetopicon':
this.moveTopIconTemplate = item.template;
break;
case 'movedownicon':
this.moveDownIconTemplate = item.template;
break;
case 'movebottomicon':
this.moveBottomIconTemplate = item.template;
break;
case 'movetotargeticon':
this.moveToTargetIconTemplate = item.template;
break;
case 'movealltotargeticon':
this.moveAllToTargetIconTemplate = item.template;
break;
case 'movetosourceicon':
this.moveToSourceIconTemplate = item.template;
break;
case 'movealltosourceicon':
this.moveAllToSourceIconTemplate = item.template;
break;
case 'targetfiltericon':
this.targetFilterIconTemplate = item.template;
break;
case 'sourcefiltericon':
this.sourceFilterIconTemplate = item.template;
break;
default:
this.itemTemplate = item.template;
break;
}
});
}
ngAfterViewChecked() {
if (this.movedUp || this.movedDown) {
let listItems = DomHandler.find(this.reorderedListElement, 'li.p-highlight');
let listItem;
if (this.movedUp)
listItem = listItems[0];
else
listItem = listItems[listItems.length - 1];
DomHandler.scrollInView(this.reorderedListElement, listItem);
this.movedUp = false;
this.movedDown = false;
this.reorderedListElement = null;
}
}
onItemClick(event, item, selectedItems, listType, callback, itemId) {
if (this.disabled) {
return;
}
let index = this.findIndexInList(item, selectedItems);
if (itemId)
this.focusedOptionIndex = itemId;
let selected = index != -1;
let metaSelection = this.itemTouched ? false : this.metaKeySelection;
if (metaSelection) {
let metaKey = event.metaKey || event.ctrlKey || event.shiftKey;
if (selected && metaKey) {
selectedItems = selectedItems.filter((_, i) => i !== index);
}
else {
if (!metaKey) {
selectedItems = [];
}
selectedItems.push(item);
}
}
else {
if (selected) {
selectedItems = selectedItems.filter((_, i) => i !== index); // Creating a new array without the selected item
}
else {
selectedItems.push(item);
}
}
this.setSelectionList(listType, selectedItems);
callback.emit({ originalEvent: event, items: selectedItems });
this.itemTouched = false;
}
onOptionMouseDown(index, listType) {
this.focused[listType === this.SOURCE_LIST ? 'sourceList' : 'targetList'] = true;
this.focusedOptionIndex = index;
}
onSourceItemDblClick() {
if (this.disabled) {
return;
}
this.moveRight();
}
onTargetItemDblClick() {
if (this.disabled) {
return;
}
this.moveLeft();
}
onFilter(event, listType) {
let query = event.target.value;
if (listType === this.SOURCE_LIST)
this.filterSource(query);
else if (listType === this.TARGET_LIST)
this.filterTarget(query);
}
filterSource(value = '') {
this.filterValueSource = value.trim().toLocaleLowerCase(this.filterLocale);
this.filter(this.source, this.SOURCE_LIST);
}
filterTarget(value = '') {
this.filterValueTarget = value.trim().toLocaleLowerCase(this.filterLocale);
this.filter(this.target, this.TARGET_LIST);
}
filter(data, listType) {
let searchFields = this.filterBy.split(',');
if (listType === this.SOURCE_LIST) {
this.visibleOptionsSource = this.filterService.filter(data, searchFields, this.filterValueSource, this.filterMatchMode, this.filterLocale);
this.onSourceFilter.emit({ query: this.filterValueSource, value: this.visibleOptionsSource });
}
else if (listType === this.TARGET_LIST) {
this.visibleOptionsTarget = this.filterService.filter(data, searchFields, this.filterValueTarget, this.filterMatchMode, this.filterLocale);
this.onTargetFilter.emit({ query: this.filterValueTarget, value: this.visibleOptionsTarget });
}
}
isItemVisible(item, listType) {
if (listType == this.SOURCE_LIST)
return this.isVisibleInList(this.visibleOptionsSource, item, this.filterValueSource);
else
return this.isVisibleInList(this.visibleOptionsTarget, item, this.filterValueTarget);
}
isEmpty(listType) {
if (listType == this.SOURCE_LIST)
return this.filterValueSource ? !this.visibleOptionsSource || this.visibleOptionsSource.length === 0 : !this.source || this.source.length === 0;
else
return this.filterValueTarget ? !this.visibleOptionsTarget || this.visibleOptionsTarget.length === 0 : !this.target || this.target.length === 0;
}
isVisibleInList(data, item, filterValue) {
if (filterValue && filterValue.trim().length) {
for (let i = 0; i < data.length; i++) {
if (item == data[i]) {
return true;
}
}
}
else {
return true;
}
}
onItemTouchEnd() {
if (this.disabled) {
return;
}
this.itemTouched = true;
}
sortByIndexInList(items, list) {
return items.sort((item1, item2) => ObjectUtils.findIndexInList(item1, list) - ObjectUtils.findIndexInList(item2, list));
}
moveUp(listElement, list, selectedItems, callback, listType) {
if (selectedItems && selectedItems.length) {
selectedItems = this.sortByIndexInList(selectedItems, list);
for (let i = 0; i < selectedItems.length; i++) {
let selectedItem = selectedItems[i];
let selectedItemIndex = ObjectUtils.findIndexInList(selectedItem, list);
if (selectedItemIndex != 0) {
let movedItem = list[selectedItemIndex];
let temp = list[selectedItemIndex - 1];
list[selectedItemIndex - 1] = movedItem;
list[selectedItemIndex] = temp;
}
else {
break;
}
}
if (this.dragdrop && ((this.filterValueSource && listType === this.SOURCE_LIST) || (this.filterValueTarget && listType === this.TARGET_LIST)))
this.filter(list, listType);
this.movedUp = true;
this.reorderedListElement = listElement;
callback.emit({ items: selectedItems });
}
}
moveTop(listElement, list, selectedItems, callback, listType) {
if (selectedItems && selectedItems.length) {
selectedItems = this.sortByIndexInList(selectedItems, list);
for (let i = 0; i < selectedItems.length; i++) {
let selectedItem = selectedItems[i];
let selectedItemIndex = ObjectUtils.findIndexInList(selectedItem, list);
if (selectedItemIndex != 0) {
let movedItem = list.splice(selectedItemIndex, 1)[0];
list.unshift(movedItem);
}
else {
break;
}
}
if (this.dragdrop && ((this.filterValueSource && listType === this.SOURCE_LIST) || (this.filterValueTarget && listType === this.TARGET_LIST)))
this.filter(list, listType);
listElement.scrollTop = 0;
callback.emit({ items: selectedItems });
}
}
moveDown(listElement, list, selectedItems, callback, listType) {
if (selectedItems && selectedItems.length) {
selectedItems = this.sortByIndexInList(selectedItems, list);
for (let i = selectedItems.length - 1; i >= 0; i--) {
let selectedItem = selectedItems[i];
let selectedItemIndex = ObjectUtils.findIndexInList(selectedItem, list);
if (selectedItemIndex != list.length - 1) {
let movedItem = list[selectedItemIndex];
let temp = list[selectedItemIndex + 1];
list[selectedItemIndex + 1] = movedItem;
list[selectedItemIndex] = temp;
}
else {
break;
}
}
if (this.dragdrop && ((this.filterValueSource && listType === this.SOURCE_LIST) || (this.filterValueTarget && listType === this.TARGET_LIST)))
this.filter(list, listType);
this.movedDown = true;
this.reorderedListElement = listElement;
callback.emit({ items: selectedItems });
}
}
moveBottom(listElement, list, selectedItems, callback, listType) {
if (selectedItems && selectedItems.length) {
selectedItems = this.sortByIndexInList(selectedItems, list);
for (let i = selectedItems.length - 1; i >= 0; i--) {
let selectedItem = selectedItems[i];
let selectedItemIndex = ObjectUtils.findIndexInList(selectedItem, list);
if (selectedItemIndex != list.length - 1) {
let movedItem = list.splice(selectedItemIndex, 1)[0];
list.push(movedItem);
}
else {
break;
}
}
if (this.dragdrop && ((this.filterValueSource && listType === this.SOURCE_LIST) || (this.filterValueTarget && listType === this.TARGET_LIST)))
this.filter(list, listType);
listElement.scrollTop = listElement.scrollHeight;
callback.emit({ items: selectedItems });
}
}
moveRight() {
if (this.selectedItemsSource && this.selectedItemsSource.length) {
for (let i = 0; i < this.selectedItemsSource.length; i++) {
let selectedItem = this.selectedItemsSource[i];
if (ObjectUtils.findIndexInList(selectedItem, this.target) == -1) {
this.target?.push(this.source?.splice(ObjectUtils.findIndexInList(selectedItem, this.source), 1)[0]);
if (this.visibleOptionsSource?.includes(selectedItem)) {
this.visibleOptionsSource.splice(ObjectUtils.findIndexInList(selectedItem, this.visibleOptionsSource), 1);
}
}
}
this.onMoveToTarget.emit({
items: this.selectedItemsSource
});
if (this.keepSelection) {
this.selectedItemsTarget = [...this.selectedItemsTarget, ...this.selectedItemsSource];
}
this.selectedItemsSource = [];
if (this.filterValueTarget) {
this.filter(this.target, this.TARGET_LIST);
}
}
}
moveAllRight() {
if (this.source) {
let movedItems = [];
for (let i = 0; i < this.source.length; i++) {
if (this.isItemVisible(this.source[i], this.SOURCE_LIST)) {
let removedItem = this.source.splice(i, 1)[0];
this.target?.push(removedItem);
movedItems.push(removedItem);
i--;
}
}
this.onMoveAllToTarget.emit({
items: movedItems
});
if (this.keepSelection) {
this.selectedItemsTarget = [...this.selectedItemsTarget, ...this.selectedItemsSource];
}
this.selectedItemsSource = [];
if (this.filterValueTarget) {
this.filter(this.target, this.TARGET_LIST);
}
this.visibleOptionsSource = [];
}
}
moveLeft() {
if (this.selectedItemsTarget && this.selectedItemsTarget.length) {
for (let i = 0; i < this.selectedItemsTarget.length; i++) {
let selectedItem = this.selectedItemsTarget[i];
if (ObjectUtils.findIndexInList(selectedItem, this.source) == -1) {
this.source?.push(this.target?.splice(ObjectUtils.findIndexInList(selectedItem, this.target), 1)[0]);
if (this.visibleOptionsTarget?.includes(selectedItem)) {
this.visibleOptionsTarget.splice(ObjectUtils.findIndexInList(selectedItem, this.visibleOptionsTarget), 1)[0];
}
}
}
this.onMoveToSource.emit({
items: this.selectedItemsTarget
});
if (this.keepSelection) {
this.selectedItemsSource = [...this.selectedItemsSource, ...this.selectedItemsTarget];
}
this.selectedItemsTarget = [];
if (this.filterValueSource) {
this.filter(this.source, this.SOURCE_LIST);
}
}
}
moveAllLeft() {
if (this.target) {
let movedItems = [];
for (let i = 0; i < this.target.length; i++) {
if (this.isItemVisible(this.target[i], this.TARGET_LIST)) {
let removedItem = this.target.splice(i, 1)[0];
this.source?.push(removedItem);
movedItems.push(removedItem);
i--;
}
}
this.onMoveAllToSource.emit({
items: movedItems
});
if (this.keepSelection) {
this.selectedItemsSource = [...this.selectedItemsSource, ...this.selectedItemsTarget];
}
this.selectedItemsTarget = [];
if (this.filterValueSource) {
this.filter(this.source, this.SOURCE_LIST);
}
this.visibleOptionsTarget = [];
}
}
isSelected(item, selectedItems) {
return this.findIndexInList(item, selectedItems) != -1;
}
itemClass(item, id, selectedItems) {
return {
'p-picklist-item': true,
'p-highlight': this.isSelected(item, selectedItems),
'p-focus': id === this.focusedOptionId,
'p-disabled': this.disabled
};
}
findIndexInList(item, selectedItems) {
return ObjectUtils.findIndexInList(item, selectedItems);
}
onDrop(event, listType) {
let isTransfer = event.previousContainer !== event.container;
let dropIndexes = this.getDropIndexes(event.previousIndex, event.currentIndex, listType, isTransfer, event.item.data);
if (listType === this.SOURCE_LIST) {
if (isTransfer) {
transferArrayItem(event.previousContainer.data, event.container.data, dropIndexes.previousIndex, dropIndexes.currentIndex);
let selectedItemIndex = ObjectUtils.findIndexInList(event.item.data, this.selectedItemsTarget);
if (selectedItemIndex != -1) {
this.selectedItemsTarget.splice(selectedItemIndex, 1);
if (this.keepSelection) {
this.selectedItemsTarget.push(event.item.data);
}
}
if (this.visibleOptionsTarget)
this.visibleOptionsTarget.splice(event.previousIndex, 1);
this.onMoveToSource.emit({ items: [event.item.data] });
}
else {
moveItemInArray(event.container.data, dropIndexes.previousIndex, dropIndexes.currentIndex);
this.onSourceReorder.emit({ items: [event.item.data] });
}
if (this.filterValueSource) {
this.filter(this.source, this.SOURCE_LIST);
}
}
else {
if (isTransfer) {
transferArrayItem(event.previousContainer.data, event.container.data, dropIndexes.previousIndex, dropIndexes.currentIndex);
let selectedItemIndex = ObjectUtils.findIndexInList(event.item.data, this.selectedItemsSource);
if (selectedItemIndex != -1) {
this.selectedItemsSource.splice(selectedItemIndex, 1);
if (this.keepSelection) {
this.selectedItemsTarget.push(event.item.data);
}
}
if (this.visibleOptionsSource)
this.visibleOptionsSource.splice(event.previousIndex, 1);
this.onMoveToTarget.emit({ items: [event.item.data] });
}
else {
moveItemInArray(event.container.data, dropIndexes.previousIndex, dropIndexes.currentIndex);
this.onTargetReorder.emit({ items: [event.item.data] });
}
if (this.filterValueTarget) {
this.filter(this.target, this.TARGET_LIST);
}
}
}
onListFocus(event, listType) {
let listElement = this.getListElement(listType);
const selectedFirstItem = DomHandler.findSingle(listElement, 'li.p-picklist-item.p-highlight') || DomHandler.findSingle(listElement, 'li.p-picklist-item');
const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, listElement.children);
this.focused[listType === this.SOURCE_LIST ? 'sourceList' : 'targetList'] = true;
const sourceIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : selectedFirstItem ? findIndex : -1;
const filteredIndex = this.findIndexInList(this.source[sourceIndex], this.visibleOptionsSource);
this.changeFocusedOptionIndex(filteredIndex, listType);
this.onFocus.emit(event);
}
onListBlur(event, listType) {
this.focused[listType === this.SOURCE_LIST ? 'sourceList' : 'targetList'] = false;
this.focusedOptionIndex = -1;
this.focusedOption = null;
this.onBlur.emit(event);
}
getListElement(listType) {
return listType === this.SOURCE_LIST ? this.listViewSourceChild?.nativeElement : this.listViewTargetChild?.nativeElement;
}
getListItems(listType) {
let listElemet = this.getListElement(listType);
return DomHandler.find(listElemet, 'li.p-picklist-item');
}
getLatestSelectedVisibleOptionIndex(visibleList, selectedItems) {
const latestSelectedItem = [...selectedItems].reverse().find((item) => visibleList.includes(item));
return latestSelectedItem !== undefined ? visibleList.indexOf(latestSelectedItem) : -1;
}
getVisibleList(listType) {
if (listType === this.SOURCE_LIST) {
return this.visibleOptionsSource && this.visibleOptionsSource.length > 0 ? this.visibleOptionsSource : this.source && this.source.length > 0 ? this.source : null;
}
return this.visibleOptionsTarget && this.visibleOptionsTarget.length > 0 ? this.visibleOptionsTarget : this.target && this.target.length > 0 ? this.target : null;
}
setSelectionList(listType, selectedItems) {
if (listType === this.SOURCE_LIST) {
this.selectedItemsSource = selectedItems;
}
else {
this.selectedItemsTarget = selectedItems;
}
}
findNextOptionIndex(index, listType) {
const items = this.getListItems(listType);
const matchedOptionIndex = [...items].findIndex((link) => link.id === index);
return matchedOptionIndex > -1 ? matchedOptionIndex + 1 : 0;
}
findPrevOptionIndex(index, listType) {
const items = this.getListItems(listType);
const matchedOptionIndex = [...items].findIndex((link) => link.id === index);
return matchedOptionIndex > -1 ? matchedOptionIndex - 1 : 0;
}
onItemKeyDown(event, selectedItems, callback, listType) {
switch (event.code) {
case 'ArrowDown':
this.onArrowDownKey(event, selectedItems, callback, listType);
break;
case 'ArrowUp':
this.onArrowUpKey(event, selectedItems, callback, listType);
break;
case 'Home':
this.onHomeKey(event, selectedItems, callback, listType);
break;
case 'End':
this.onEndKey(event, selectedItems, callback, listType);
break;
case 'Enter':
this.onEnterKey(event, selectedItems, callback, listType);
break;
case 'Space':
this.onSpaceKey(event, selectedItems, callback, listType);
break;
case 'KeyA':
if (event.ctrlKey) {
this.setSelectionList(listType, this.getVisibleList(listType));
callback.emit({ items: selectedItems });
event.preventDefault();
}
default:
break;
}
}
getFocusedOption(index, listType) {
if (index === -1)
return null;
if (listType === this.SOURCE_LIST) {
return this.visibleOptionsSource && this.visibleOptionsSource.length ? this.visibleOptionsSource[index] : this.source && this.source.length ? this.source[index] : null;
}
return this.visibleOptionsTarget && this.visibleOptionsTarget.length ? this.visibleOptionsTarget[index] : this.target && this.target.length ? this.target[index] : null;
}
changeFocusedOptionIndex(index, listType) {
const items = this.getListItems(listType);
if (items?.length > 0) {
let order = index >= items.length ? items.length - 1 : index < 0 ? 0 : index;
this.focusedOptionIndex = items[order].getAttribute('id');
this.focusedOption = this.getFocusedOption(order, listType);
this.scrollInView(items[order].getAttribute('id'), listType);
}
}
scrollInView(id, listType) {
const element = DomHandler.findSingle(this.getListElement(listType), `li[id="${id}"]`);
if (element) {
element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
}
}
onArrowDownKey(event, selectedItems, callback, listType) {
const optionIndex = this.findNextOptionIndex(this.focusedOptionIndex, listType);
this.changeFocusedOptionIndex(optionIndex, listType);
if (event.shiftKey) {
this.onEnterKey(event, selectedItems, callback, listType);
}
event.preventDefault();
}
onArrowUpKey(event, selectedItems, callback, listType) {
const optionIndex = this.findPrevOptionIndex(this.focusedOptionIndex, listType);
this.changeFocusedOptionIndex(optionIndex, listType);
if (event.shiftKey) {
this.onEnterKey(event, selectedItems, callback, listType);
}
event.preventDefault();
}
onEnterKey(event, selectedItems, callback, listType) {
this.onItemClick(event, this.focusedOption, selectedItems, listType, callback);
event.preventDefault();
}
onSpaceKey(event, selectedItems, callback, listType) {
event.preventDefault();
if (event.shiftKey && selectedItems && selectedItems.length > 0) {
let visibleList = this.getVisibleList(listType);
let lastSelectedIndex = this.getLatestSelectedVisibleOptionIndex(visibleList, selectedItems);
if (lastSelectedIndex !== -1) {
let focusedIndex = ObjectUtils.findIndexInList(this.focusedOption, visibleList);
selectedItems = [...visibleList.slice(Math.min(lastSelectedIndex, focusedIndex), Math.max(lastSelectedIndex, focusedIndex) + 1)];
this.setSelectionList(listType, selectedItems);
callback.emit({ items: selectedItems });
return;
}
}
this.onEnterKey(event, selectedItems, callback, listType);
}
onHomeKey(event, selectedItems, callback, listType) {
if (event.ctrlKey && event.shiftKey) {
let visibleList = this.getVisibleList(listType);
let focusedIndex = ObjectUtils.findIndexInList(this.focusedOption, visibleList);
selectedItems = [...visibleList.slice(0, focusedIndex + 1)];
this.setSelectionList(listType, selectedItems);
callback.emit({ items: selectedItems });
}
else {
this.changeFocusedOptionIndex(0, listType);
}
event.preventDefault();
}
onEndKey(event, selectedItems, callback, listType) {
let visibleList = this.getVisibleList(listType);
let lastIndex = visibleList && visibleList.length > 0 ? visibleList.length - 1 : null;
if (lastIndex === null)
return;
if (event.ctrlKey && event.shiftKey) {
let focusedIndex = ObjectUtils.findIndexInList(this.focusedOption, visibleList);
selectedItems = [...visibleList.slice(focusedIndex, lastIndex)];
this.setSelectionList(listType, selectedItems);
callback.emit({ items: selectedItems });
}
else {
this.changeFocusedOptionIndex(lastIndex, listType);
}
event.preventDefault();
}
getDropIndexes(fromIndex, toIndex, droppedList, isTransfer, data) {
let previousIndex, currentIndex;
if (droppedList === this.SOURCE_LIST) {
previousIndex = isTransfer ? (this.filterValueTarget ? ObjectUtils.findIndexInList(data, this.target) : fromIndex) : this.filterValueSource ? ObjectUtils.findIndexInList(data, this.source) : fromIndex;
currentIndex = this.filterValueSource ? this.findFilteredCurrentIndex(this.visibleOptionsSource, toIndex, this.source) : toIndex;
}
else {
previousIndex = isTransfer ? (this.filterValueSource ? ObjectUtils.findIndexInList(data, this.source) : fromIndex) : this.filterValueTarget ? ObjectUtils.findIndexInList(data, this.target) : fromIndex;
currentIndex = this.filterValueTarget ? this.findFilteredCurrentIndex(this.visibleOptionsTarget, toIndex, this.target) : toIndex;
}
return { previousIndex, currentIndex };
}
findFilteredCurrentIndex(visibleOptions, index, options) {
if (visibleOptions.length === index) {
let toIndex = ObjectUtils.findIndexInList(visibleOptions[index - 1], options);
return toIndex + 1;
}
else {
return ObjectUtils.findIndexInList(visibleOptions[index], options);
}
}
resetSourceFilter() {
this.visibleOptionsSource = null;
this.filterValueSource = null;
this.sourceFilterViewChild && (this.sourceFilterViewChild.nativeElement.value = '');
}
resetTargetFilter() {
this.visibleOptionsTarget = null;
this.filterValueTarget = null;
this.targetFilterViewChild && (this.targetFilterViewChild.nativeElement.value = '');
}
resetFilter() {
this.resetSourceFilter();
this.resetTargetFilter();
}
findNextItem(item) {
let nextItem = item.nextElementSibling;
if (nextItem)
return !DomHandler.hasClass(nextItem, 'p-picklist-item') || DomHandler.isHidden(nextItem) ? this.findNextItem(nextItem) : nextItem;
else
return null;
}
findPrevItem(item) {
let prevItem = item.previousElementSibling;
if (prevItem)
return !DomHandler.hasClass(prevItem, 'p-picklist-item') || DomHandler.isHidden(prevItem) ? this.findPrevItem(prevItem) : prevItem;
else
return null;
}
initMedia() {
if (isPlatformBrowser(this.platformId)) {
this.media = this.window.matchMedia(`(max-width: ${this.breakpoint})`);
this.viewChanged = this.media.matches;
this.bindMediaChangeListener();
}
}
destroyMedia() {
this.unbindMediaChangeListener();
}
bindMediaChangeListener() {
if (this.media && !this.mediaChangeListener) {
this.mediaChangeListener = this.renderer.listen(this.media, 'change', (event) => {
this.viewChanged = event.matches;
this.cd.markForCheck();
});
}
}
unbindMediaChangeListener() {
if (this.mediaChangeListener) {
this.mediaChangeListener();
this.mediaChangeListener = null;
}
}
createStyle() {
if (isPlatformBrowser(this.platformId)) {
if (!this.styleElement) {
this.renderer.setAttribute(this.el.nativeElement.children[0], this.id, '');
this.styleElement = this.renderer.createElement('style');
this.renderer.setAttribute(this.styleElement, 'type', 'text/css');
this.renderer.appendChild(this.document.head, this.styleElement);
let innerHTML = `
@media screen and (max-width: ${this.breakpoint}) {
.p-picklist[${this.id}] {
flex-direction: column;
}
.p-picklist[${this.id}] .p-picklist-buttons {
padding: var(--content-padding);
flex-direction: row;
}
.p-picklist[${this.id}] .p-picklist-buttons .p-button {
margin-right: var(--inline-spacing);
margin-bottom: 0;
}
.p-picklist[${this.id}] .p-picklist-buttons .p-button:last-child {
margin-right: 0;
}
}`;
this.renderer.setProperty(this.styleElement, 'innerHTML', innerHTML);
DomHandler.setAttribute(this.styleElement, 'nonce', this.config?.csp()?.nonce);
}
}
}
sourceMoveDisabled() {
if (this.disabled || !this.selectedItemsSource.length) {
return true;
}
}
targetMoveDisabled() {
if (this.disabled || !this.selectedItemsTarget.length) {
return true;
}
}
moveRightDisabled() {
return this.disabled || ObjectUtils.isEmpty(this.selectedItemsSource);
}
moveLeftDisabled() {
return this.disabled || ObjectUtils.isEmpty(this.selectedItemsTarget);
}
moveAllRightDisabled() {
return this.disabled || ObjectUtils.isEmpty(this.source);
}
moveAllLeftDisabled() {
return this.disabled || ObjectUtils.isEmpty(this.target);
}
destroyStyle() {
if (this.styleElement) {
this.renderer.removeChild(this.document.head, this.styleElement);
this.styleElement = null;
``;
}
}
ngOnDestroy() {
this.destroyStyle();
this.destroyMedia();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: PickList, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1.FilterService }, { token: i1.PrimeNGConfig }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "18.0.1", type: PickList, selector: "p-pickList", inputs: { source: "source", target: "target", sourceHeader: "sourceHeader", tabindex: ["tabindex", "tabindex", numberAttribute], rightButtonAriaLabel: "rightButtonAriaLabel", leftButtonAriaLabel: "leftButtonAriaLabel", allRightButtonAriaLabel: "allRightButtonAriaLabel", allLeftButtonAriaLabel: "allLeftButtonAriaLabel", upButtonAriaLabel: "upButtonAriaLabel", downButtonAriaLabel: "downButtonAriaLabel", topButtonAriaLabel: "topButtonAriaLabel", bottomButtonAriaLabel: "bottomButtonAriaLabel", targetHeader: "targetHeader", responsive: ["responsive", "responsive", booleanAttribute], filterBy: "filterBy", filterLocale: "filterLocale", trackBy: "trackBy", sourceTrackBy: "sourceTrackBy", targetTrackBy: "targetTrackBy", showSourceFilter: ["showSourceFilter", "showSourceFilter", booleanAttribute], showTargetFilter: ["showTargetFilter", "showTargetFilter", booleanAttribute], metaKeySelection: ["metaKeySelection", "metaKeySelection", booleanAttribute], dragdrop: ["dragdrop", "dragdrop", booleanAttribute], style: "style", styleClass: "styleClass", sourceStyle: "sourceStyle", targetStyle: "targetStyle", showSourceControls: ["showSourceControls", "showSourceControls", booleanAttribute], showTargetControls: ["showTargetControls", "showTargetControls", booleanAttribute], sourceFilterPlaceholder: "sourceFilterPlaceholder", targetFilterPlaceholder: "targetFilterPlaceholder", disabled: ["disabled", "disabled", booleanAttribute], ariaSourceFilterLabel: "ariaSourceFilterLabel", ariaTargetFilterLabel: "ariaTargetFilterLabel", filterMatchMode: "filterMatchMode", stripedRows: ["stripedRows", "stripedRows", booleanAttribute], keepSelection: ["keepSelection", "keepSelection", booleanAttribute], breakpoint: "breakpoint" }, outputs: { onMoveToSource: "onMoveToSource", onMoveAllToSource: "onMoveAllToSource", onMoveAllToTarget: "onMoveAllToTarget", onMoveToTarget: "onMoveToTarget", onSourceReorder: "onSourceReorder", onTargetReorder: "onTargetReorder", onSourceSelect: "onSourceSelect", onTargetSelect: "onTargetSelect", onSourceFilter: "onSourceFilter", onTargetFilter: "onTargetFilter", onFocus: "onFocus", onBlur: "onBlur" }, host: { classAttribute: "p-element" }, queries: [{ propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "listViewSourceChild", first: true, predicate: ["sourcelist"], descendants: true }, { propertyName: "listViewTargetChild", first: true, predicate: ["targetlist"], descendants: true }, { propertyName: "sourceFilterViewChild", first: true, predicate: ["sourceFilter"], descendants: true }, { propertyName: "targetFilterViewChild", first: true, predicate: ["targetFilter"], descendants: true }], ngImport: i0, template: `
<div [class]="styleClass" [ngStyle]="style" [ngClass]="{ 'p-picklist p-component': true, 'p-picklist-striped': stripedRows }" cdkDropListGroup [attr.data-pc-name]="'picklist'" [attr.data-pc-section]="'root'">
<div class="p-picklist-buttons p-picklist-source-controls" *ngIf="sho