UNPKG

138 kBJavaScriptView Raw
1import { Injectable, EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, ElementRef, NgZone, ChangeDetectorRef, Input, Output, ViewChild, ContentChildren, Directive, HostListener, Optional, NgModule } from '@angular/core';
2import { CommonModule } from '@angular/common';
3import { PrimeTemplate, SharedModule } from 'primeng/api';
4import { PaginatorModule } from 'primeng/paginator';
5import { DomHandler } from 'primeng/dom';
6import { ObjectUtils, FilterUtils } from 'primeng/utils';
7import { Subject } from 'rxjs';
8import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
9
10class TableService {
11 constructor() {
12 this.sortSource = new Subject();
13 this.selectionSource = new Subject();
14 this.contextMenuSource = new Subject();
15 this.valueSource = new Subject();
16 this.totalRecordsSource = new Subject();
17 this.columnsSource = new Subject();
18 this.sortSource$ = this.sortSource.asObservable();
19 this.selectionSource$ = this.selectionSource.asObservable();
20 this.contextMenuSource$ = this.contextMenuSource.asObservable();
21 this.valueSource$ = this.valueSource.asObservable();
22 this.totalRecordsSource$ = this.totalRecordsSource.asObservable();
23 this.columnsSource$ = this.columnsSource.asObservable();
24 }
25 onSort(sortMeta) {
26 this.sortSource.next(sortMeta);
27 }
28 onSelectionChange() {
29 this.selectionSource.next();
30 }
31 onContextMenu(data) {
32 this.contextMenuSource.next(data);
33 }
34 onValueChange(value) {
35 this.valueSource.next(value);
36 }
37 onTotalRecordsChange(value) {
38 this.totalRecordsSource.next(value);
39 }
40 onColumnsChange(columns) {
41 this.columnsSource.next(columns);
42 }
43}
44TableService.decorators = [
45 { type: Injectable }
46];
47class Table {
48 constructor(el, zone, tableService, cd) {
49 this.el = el;
50 this.zone = zone;
51 this.tableService = tableService;
52 this.cd = cd;
53 this.pageLinks = 5;
54 this.alwaysShowPaginator = true;
55 this.paginatorPosition = 'bottom';
56 this.paginatorDropdownScrollHeight = '200px';
57 this.currentPageReportTemplate = '{currentPage} of {totalPages}';
58 this.showPageLinks = true;
59 this.defaultSortOrder = 1;
60 this.sortMode = 'single';
61 this.resetPageOnSort = true;
62 this.selectionChange = new EventEmitter();
63 this.contextMenuSelectionChange = new EventEmitter();
64 this.contextMenuSelectionMode = "separate";
65 this.rowTrackBy = (index, item) => item;
66 this.lazy = false;
67 this.lazyLoadOnInit = true;
68 this.compareSelectionBy = 'deepEquals';
69 this.csvSeparator = ',';
70 this.exportFilename = 'download';
71 this.filters = {};
72 this.filterDelay = 300;
73 this.expandedRowKeys = {};
74 this.editingRowKeys = {};
75 this.rowExpandMode = 'multiple';
76 this.virtualScrollDelay = 150;
77 this.virtualRowHeight = 28;
78 this.columnResizeMode = 'fit';
79 this.loadingIcon = 'pi pi-spinner';
80 this.showLoader = true;
81 this.stateStorage = 'session';
82 this.editMode = 'cell';
83 this.onRowSelect = new EventEmitter();
84 this.onRowUnselect = new EventEmitter();
85 this.onPage = new EventEmitter();
86 this.onSort = new EventEmitter();
87 this.onFilter = new EventEmitter();
88 this.onLazyLoad = new EventEmitter();
89 this.onRowExpand = new EventEmitter();
90 this.onRowCollapse = new EventEmitter();
91 this.onContextMenuSelect = new EventEmitter();
92 this.onColResize = new EventEmitter();
93 this.onColReorder = new EventEmitter();
94 this.onRowReorder = new EventEmitter();
95 this.onEditInit = new EventEmitter();
96 this.onEditComplete = new EventEmitter();
97 this.onEditCancel = new EventEmitter();
98 this.onHeaderCheckboxToggle = new EventEmitter();
99 this.sortFunction = new EventEmitter();
100 this.firstChange = new EventEmitter();
101 this.rowsChange = new EventEmitter();
102 this.onStateSave = new EventEmitter();
103 this.onStateRestore = new EventEmitter();
104 this._value = [];
105 this._totalRecords = 0;
106 this._first = 0;
107 this.selectionKeys = {};
108 this._sortOrder = 1;
109 }
110 ngOnInit() {
111 if (this.lazy && this.lazyLoadOnInit) {
112 if (!this.virtualScroll) {
113 this.onLazyLoad.emit(this.createLazyLoadMetadata());
114 }
115 if (this.restoringFilter) {
116 this.restoringFilter = false;
117 }
118 }
119 this.initialized = true;
120 }
121 ngAfterContentInit() {
122 this.templates.forEach((item) => {
123 switch (item.getType()) {
124 case 'caption':
125 this.captionTemplate = item.template;
126 break;
127 case 'header':
128 this.headerTemplate = item.template;
129 break;
130 case 'body':
131 this.bodyTemplate = item.template;
132 break;
133 case 'loadingbody':
134 this.loadingBodyTemplate = item.template;
135 break;
136 case 'footer':
137 this.footerTemplate = item.template;
138 break;
139 case 'summary':
140 this.summaryTemplate = item.template;
141 break;
142 case 'colgroup':
143 this.colGroupTemplate = item.template;
144 break;
145 case 'rowexpansion':
146 this.expandedRowTemplate = item.template;
147 break;
148 case 'frozenrows':
149 this.frozenRowsTemplate = item.template;
150 break;
151 case 'frozenheader':
152 this.frozenHeaderTemplate = item.template;
153 break;
154 case 'frozenbody':
155 this.frozenBodyTemplate = item.template;
156 break;
157 case 'frozenfooter':
158 this.frozenFooterTemplate = item.template;
159 break;
160 case 'frozencolgroup':
161 this.frozenColGroupTemplate = item.template;
162 break;
163 case 'emptymessage':
164 this.emptyMessageTemplate = item.template;
165 break;
166 case 'paginatorleft':
167 this.paginatorLeftTemplate = item.template;
168 break;
169 case 'paginatorright':
170 this.paginatorRightTemplate = item.template;
171 break;
172 }
173 });
174 }
175 ngAfterViewInit() {
176 if (this.isStateful() && this.resizableColumns) {
177 this.restoreColumnWidths();
178 }
179 }
180 clearCache() {
181 if (this.scrollable) {
182 if (this.scrollableViewChild) {
183 this.scrollableViewChild.clearCache();
184 }
185 if (this.scrollableFrozenViewChild) {
186 this.scrollableViewChild.clearCache();
187 }
188 }
189 }
190 ngOnChanges(simpleChange) {
191 if (simpleChange.value) {
192 if (this.isStateful() && !this.stateRestored) {
193 this.restoreState();
194 }
195 this._value = simpleChange.value.currentValue;
196 if (!this.lazy) {
197 this.clearCache();
198 this.totalRecords = (this._value ? this._value.length : 0);
199 if (this.sortMode == 'single' && this.sortField)
200 this.sortSingle();
201 else if (this.sortMode == 'multiple' && this.multiSortMeta)
202 this.sortMultiple();
203 else if (this.hasFilter()) //sort already filters
204 this._filter();
205 }
206 this.tableService.onValueChange(simpleChange.value.currentValue);
207 }
208 if (simpleChange.columns) {
209 this._columns = simpleChange.columns.currentValue;
210 this.tableService.onColumnsChange(simpleChange.columns.currentValue);
211 if (this._columns && this.isStateful() && this.reorderableColumns && !this.columnOrderStateRestored) {
212 this.restoreColumnOrder();
213 }
214 }
215 if (simpleChange.sortField) {
216 this._sortField = simpleChange.sortField.currentValue;
217 //avoid triggering lazy load prior to lazy initialization at onInit
218 if (!this.lazy || this.initialized) {
219 if (this.sortMode === 'single') {
220 this.sortSingle();
221 }
222 }
223 }
224 if (simpleChange.sortOrder) {
225 this._sortOrder = simpleChange.sortOrder.currentValue;
226 //avoid triggering lazy load prior to lazy initialization at onInit
227 if (!this.lazy || this.initialized) {
228 if (this.sortMode === 'single') {
229 this.sortSingle();
230 }
231 }
232 }
233 if (simpleChange.multiSortMeta) {
234 this._multiSortMeta = simpleChange.multiSortMeta.currentValue;
235 if (this.sortMode === 'multiple') {
236 this.sortMultiple();
237 }
238 }
239 if (simpleChange.selection) {
240 this._selection = simpleChange.selection.currentValue;
241 if (!this.preventSelectionSetterPropagation) {
242 this.updateSelectionKeys();
243 this.tableService.onSelectionChange();
244 }
245 this.preventSelectionSetterPropagation = false;
246 }
247 }
248 get value() {
249 return this._value;
250 }
251 set value(val) {
252 this._value = val;
253 }
254 get columns() {
255 return this._columns;
256 }
257 set columns(cols) {
258 this._columns = cols;
259 }
260 get first() {
261 return this._first;
262 }
263 set first(val) {
264 this._first = val;
265 }
266 get rows() {
267 return this._rows;
268 }
269 set rows(val) {
270 this._rows = val;
271 }
272 get totalRecords() {
273 return this._totalRecords;
274 }
275 set totalRecords(val) {
276 this._totalRecords = val;
277 this.tableService.onTotalRecordsChange(this._totalRecords);
278 }
279 get sortField() {
280 return this._sortField;
281 }
282 set sortField(val) {
283 this._sortField = val;
284 }
285 get sortOrder() {
286 return this._sortOrder;
287 }
288 set sortOrder(val) {
289 this._sortOrder = val;
290 }
291 get multiSortMeta() {
292 return this._multiSortMeta;
293 }
294 set multiSortMeta(val) {
295 this._multiSortMeta = val;
296 }
297 get selection() {
298 return this._selection;
299 }
300 set selection(val) {
301 this._selection = val;
302 }
303 updateSelectionKeys() {
304 if (this.dataKey && this._selection) {
305 this.selectionKeys = {};
306 if (Array.isArray(this._selection)) {
307 for (let data of this._selection) {
308 this.selectionKeys[String(ObjectUtils.resolveFieldData(data, this.dataKey))] = 1;
309 }
310 }
311 else {
312 this.selectionKeys[String(ObjectUtils.resolveFieldData(this._selection, this.dataKey))] = 1;
313 }
314 }
315 }
316 onPageChange(event) {
317 this.first = event.first;
318 this.rows = event.rows;
319 if (this.lazy) {
320 this.onLazyLoad.emit(this.createLazyLoadMetadata());
321 }
322 this.onPage.emit({
323 first: this.first,
324 rows: this.rows
325 });
326 this.firstChange.emit(this.first);
327 this.rowsChange.emit(this.rows);
328 this.tableService.onValueChange(this.value);
329 if (this.isStateful()) {
330 this.saveState();
331 }
332 this.anchorRowIndex = null;
333 if (this.scrollable) {
334 this.resetScrollTop();
335 }
336 }
337 sort(event) {
338 let originalEvent = event.originalEvent;
339 if (this.sortMode === 'single') {
340 this._sortOrder = (this.sortField === event.field) ? this.sortOrder * -1 : this.defaultSortOrder;
341 this._sortField = event.field;
342 this.sortSingle();
343 if (this.resetPageOnSort) {
344 this._first = 0;
345 this.firstChange.emit(this._first);
346 if (this.scrollable) {
347 this.resetScrollTop();
348 }
349 }
350 }
351 if (this.sortMode === 'multiple') {
352 let metaKey = originalEvent.metaKey || originalEvent.ctrlKey;
353 let sortMeta = this.getSortMeta(event.field);
354 if (sortMeta) {
355 if (!metaKey) {
356 this._multiSortMeta = [{ field: event.field, order: sortMeta.order * -1 }];
357 if (this.resetPageOnSort) {
358 this._first = 0;
359 this.firstChange.emit(this._first);
360 if (this.scrollable) {
361 this.resetScrollTop();
362 }
363 }
364 }
365 else {
366 sortMeta.order = sortMeta.order * -1;
367 }
368 }
369 else {
370 if (!metaKey || !this.multiSortMeta) {
371 this._multiSortMeta = [];
372 if (this.resetPageOnSort) {
373 this._first = 0;
374 this.firstChange.emit(this._first);
375 }
376 }
377 this._multiSortMeta.push({ field: event.field, order: this.defaultSortOrder });
378 }
379 this.sortMultiple();
380 }
381 if (this.isStateful()) {
382 this.saveState();
383 }
384 this.anchorRowIndex = null;
385 }
386 sortSingle() {
387 if (this.sortField && this.sortOrder) {
388 if (this.restoringSort) {
389 this.restoringSort = false;
390 }
391 if (this.lazy) {
392 this.onLazyLoad.emit(this.createLazyLoadMetadata());
393 }
394 else if (this.value) {
395 if (this.customSort) {
396 this.sortFunction.emit({
397 data: this.value,
398 mode: this.sortMode,
399 field: this.sortField,
400 order: this.sortOrder
401 });
402 }
403 else {
404 this.value.sort((data1, data2) => {
405 let value1 = ObjectUtils.resolveFieldData(data1, this.sortField);
406 let value2 = ObjectUtils.resolveFieldData(data2, this.sortField);
407 let result = null;
408 if (value1 == null && value2 != null)
409 result = -1;
410 else if (value1 != null && value2 == null)
411 result = 1;
412 else if (value1 == null && value2 == null)
413 result = 0;
414 else if (typeof value1 === 'string' && typeof value2 === 'string')
415 result = value1.localeCompare(value2);
416 else
417 result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
418 return (this.sortOrder * result);
419 });
420 this._value = [...this.value];
421 }
422 if (this.hasFilter()) {
423 this._filter();
424 }
425 }
426 let sortMeta = {
427 field: this.sortField,
428 order: this.sortOrder
429 };
430 this.onSort.emit(sortMeta);
431 this.tableService.onSort(sortMeta);
432 }
433 }
434 sortMultiple() {
435 if (this.multiSortMeta) {
436 if (this.lazy) {
437 this.onLazyLoad.emit(this.createLazyLoadMetadata());
438 }
439 else if (this.value) {
440 if (this.customSort) {
441 this.sortFunction.emit({
442 data: this.value,
443 mode: this.sortMode,
444 multiSortMeta: this.multiSortMeta
445 });
446 }
447 else {
448 this.value.sort((data1, data2) => {
449 return this.multisortField(data1, data2, this.multiSortMeta, 0);
450 });
451 this._value = [...this.value];
452 }
453 if (this.hasFilter()) {
454 this._filter();
455 }
456 }
457 this.onSort.emit({
458 multisortmeta: this.multiSortMeta
459 });
460 this.tableService.onSort(this.multiSortMeta);
461 }
462 }
463 multisortField(data1, data2, multiSortMeta, index) {
464 let value1 = ObjectUtils.resolveFieldData(data1, multiSortMeta[index].field);
465 let value2 = ObjectUtils.resolveFieldData(data2, multiSortMeta[index].field);
466 let result = null;
467 if (value1 == null && value2 != null)
468 result = -1;
469 else if (value1 != null && value2 == null)
470 result = 1;
471 else if (value1 == null && value2 == null)
472 result = 0;
473 else if (typeof value1 == 'string' || value1 instanceof String) {
474 if (value1.localeCompare && (value1 != value2)) {
475 return (multiSortMeta[index].order * value1.localeCompare(value2));
476 }
477 }
478 else {
479 result = (value1 < value2) ? -1 : 1;
480 }
481 if (value1 == value2) {
482 return (multiSortMeta.length - 1) > (index) ? (this.multisortField(data1, data2, multiSortMeta, index + 1)) : 0;
483 }
484 return (multiSortMeta[index].order * result);
485 }
486 getSortMeta(field) {
487 if (this.multiSortMeta && this.multiSortMeta.length) {
488 for (let i = 0; i < this.multiSortMeta.length; i++) {
489 if (this.multiSortMeta[i].field === field) {
490 return this.multiSortMeta[i];
491 }
492 }
493 }
494 return null;
495 }
496 isSorted(field) {
497 if (this.sortMode === 'single') {
498 return (this.sortField && this.sortField === field);
499 }
500 else if (this.sortMode === 'multiple') {
501 let sorted = false;
502 if (this.multiSortMeta) {
503 for (let i = 0; i < this.multiSortMeta.length; i++) {
504 if (this.multiSortMeta[i].field == field) {
505 sorted = true;
506 break;
507 }
508 }
509 }
510 return sorted;
511 }
512 }
513 handleRowClick(event) {
514 let target = event.originalEvent.target;
515 let targetNode = target.nodeName;
516 let parentNode = target.parentElement && target.parentElement.nodeName;
517 if (targetNode == 'INPUT' || targetNode == 'BUTTON' || targetNode == 'A' ||
518 parentNode == 'INPUT' || parentNode == 'BUTTON' || parentNode == 'A' ||
519 (DomHandler.hasClass(event.originalEvent.target, 'p-clickable'))) {
520 return;
521 }
522 if (this.selectionMode) {
523 this.preventSelectionSetterPropagation = true;
524 if (this.isMultipleSelectionMode() && event.originalEvent.shiftKey && this.anchorRowIndex != null) {
525 DomHandler.clearSelection();
526 if (this.rangeRowIndex != null) {
527 this.clearSelectionRange(event.originalEvent);
528 }
529 this.rangeRowIndex = event.rowIndex;
530 this.selectRange(event.originalEvent, event.rowIndex);
531 }
532 else {
533 let rowData = event.rowData;
534 let selected = this.isSelected(rowData);
535 let metaSelection = this.rowTouched ? false : this.metaKeySelection;
536 let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rowData, this.dataKey)) : null;
537 this.anchorRowIndex = event.rowIndex;
538 this.rangeRowIndex = event.rowIndex;
539 if (metaSelection) {
540 let metaKey = event.originalEvent.metaKey || event.originalEvent.ctrlKey;
541 if (selected && metaKey) {
542 if (this.isSingleSelectionMode()) {
543 this._selection = null;
544 this.selectionKeys = {};
545 this.selectionChange.emit(null);
546 }
547 else {
548 let selectionIndex = this.findIndexInSelection(rowData);
549 this._selection = this.selection.filter((val, i) => i != selectionIndex);
550 this.selectionChange.emit(this.selection);
551 if (dataKeyValue) {
552 delete this.selectionKeys[dataKeyValue];
553 }
554 }
555 this.onRowUnselect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' });
556 }
557 else {
558 if (this.isSingleSelectionMode()) {
559 this._selection = rowData;
560 this.selectionChange.emit(rowData);
561 if (dataKeyValue) {
562 this.selectionKeys = {};
563 this.selectionKeys[dataKeyValue] = 1;
564 }
565 }
566 else if (this.isMultipleSelectionMode()) {
567 if (metaKey) {
568 this._selection = this.selection || [];
569 }
570 else {
571 this._selection = [];
572 this.selectionKeys = {};
573 }
574 this._selection = [...this.selection, rowData];
575 this.selectionChange.emit(this.selection);
576 if (dataKeyValue) {
577 this.selectionKeys[dataKeyValue] = 1;
578 }
579 }
580 this.onRowSelect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row', index: event.rowIndex });
581 }
582 }
583 else {
584 if (this.selectionMode === 'single') {
585 if (selected) {
586 this._selection = null;
587 this.selectionKeys = {};
588 this.selectionChange.emit(this.selection);
589 this.onRowUnselect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' });
590 }
591 else {
592 this._selection = rowData;
593 this.selectionChange.emit(this.selection);
594 this.onRowSelect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row', index: event.rowIndex });
595 if (dataKeyValue) {
596 this.selectionKeys = {};
597 this.selectionKeys[dataKeyValue] = 1;
598 }
599 }
600 }
601 else if (this.selectionMode === 'multiple') {
602 if (selected) {
603 let selectionIndex = this.findIndexInSelection(rowData);
604 this._selection = this.selection.filter((val, i) => i != selectionIndex);
605 this.selectionChange.emit(this.selection);
606 this.onRowUnselect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' });
607 if (dataKeyValue) {
608 delete this.selectionKeys[dataKeyValue];
609 }
610 }
611 else {
612 this._selection = this.selection ? [...this.selection, rowData] : [rowData];
613 this.selectionChange.emit(this.selection);
614 this.onRowSelect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row', index: event.rowIndex });
615 if (dataKeyValue) {
616 this.selectionKeys[dataKeyValue] = 1;
617 }
618 }
619 }
620 }
621 }
622 this.tableService.onSelectionChange();
623 if (this.isStateful()) {
624 this.saveState();
625 }
626 }
627 this.rowTouched = false;
628 }
629 handleRowTouchEnd(event) {
630 this.rowTouched = true;
631 }
632 handleRowRightClick(event) {
633 if (this.contextMenu) {
634 const rowData = event.rowData;
635 if (this.contextMenuSelectionMode === 'separate') {
636 this.contextMenuSelection = rowData;
637 this.contextMenuSelectionChange.emit(rowData);
638 this.onContextMenuSelect.emit({ originalEvent: event.originalEvent, data: rowData, index: event.rowIndex });
639 this.contextMenu.show(event.originalEvent);
640 this.tableService.onContextMenu(rowData);
641 }
642 else if (this.contextMenuSelectionMode === 'joint') {
643 this.preventSelectionSetterPropagation = true;
644 let selected = this.isSelected(rowData);
645 let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rowData, this.dataKey)) : null;
646 if (!selected) {
647 if (this.isSingleSelectionMode()) {
648 this.selection = rowData;
649 this.selectionChange.emit(rowData);
650 }
651 else if (this.isMultipleSelectionMode()) {
652 this.selection = [rowData];
653 this.selectionChange.emit(this.selection);
654 }
655 if (dataKeyValue) {
656 this.selectionKeys[dataKeyValue] = 1;
657 }
658 }
659 this.contextMenu.show(event.originalEvent);
660 this.onContextMenuSelect.emit({ originalEvent: event, data: rowData, index: event.rowIndex });
661 }
662 }
663 }
664 selectRange(event, rowIndex) {
665 let rangeStart, rangeEnd;
666 if (this.anchorRowIndex > rowIndex) {
667 rangeStart = rowIndex;
668 rangeEnd = this.anchorRowIndex;
669 }
670 else if (this.anchorRowIndex < rowIndex) {
671 rangeStart = this.anchorRowIndex;
672 rangeEnd = rowIndex;
673 }
674 else {
675 rangeStart = rowIndex;
676 rangeEnd = rowIndex;
677 }
678 if (this.lazy && this.paginator) {
679 rangeStart -= this.first;
680 rangeEnd -= this.first;
681 }
682 for (let i = rangeStart; i <= rangeEnd; i++) {
683 let rangeRowData = this.filteredValue ? this.filteredValue[i] : this.value[i];
684 if (!this.isSelected(rangeRowData)) {
685 this._selection = [...this.selection, rangeRowData];
686 let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rangeRowData, this.dataKey)) : null;
687 if (dataKeyValue) {
688 this.selectionKeys[dataKeyValue] = 1;
689 }
690 this.onRowSelect.emit({ originalEvent: event, data: rangeRowData, type: 'row' });
691 }
692 }
693 this.selectionChange.emit(this.selection);
694 }
695 clearSelectionRange(event) {
696 let rangeStart, rangeEnd;
697 if (this.rangeRowIndex > this.anchorRowIndex) {
698 rangeStart = this.anchorRowIndex;
699 rangeEnd = this.rangeRowIndex;
700 }
701 else if (this.rangeRowIndex < this.anchorRowIndex) {
702 rangeStart = this.rangeRowIndex;
703 rangeEnd = this.anchorRowIndex;
704 }
705 else {
706 rangeStart = this.rangeRowIndex;
707 rangeEnd = this.rangeRowIndex;
708 }
709 for (let i = rangeStart; i <= rangeEnd; i++) {
710 let rangeRowData = this.value[i];
711 let selectionIndex = this.findIndexInSelection(rangeRowData);
712 this._selection = this.selection.filter((val, i) => i != selectionIndex);
713 let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rangeRowData, this.dataKey)) : null;
714 if (dataKeyValue) {
715 delete this.selectionKeys[dataKeyValue];
716 }
717 this.onRowUnselect.emit({ originalEvent: event, data: rangeRowData, type: 'row' });
718 }
719 }
720 isSelected(rowData) {
721 if (rowData && this.selection) {
722 if (this.dataKey) {
723 return this.selectionKeys[ObjectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined;
724 }
725 else {
726 if (this.selection instanceof Array)
727 return this.findIndexInSelection(rowData) > -1;
728 else
729 return this.equals(rowData, this.selection);
730 }
731 }
732 return false;
733 }
734 findIndexInSelection(rowData) {
735 let index = -1;
736 if (this.selection && this.selection.length) {
737 for (let i = 0; i < this.selection.length; i++) {
738 if (this.equals(rowData, this.selection[i])) {
739 index = i;
740 break;
741 }
742 }
743 }
744 return index;
745 }
746 toggleRowWithRadio(event, rowData) {
747 this.preventSelectionSetterPropagation = true;
748 if (this.selection != rowData) {
749 this._selection = rowData;
750 this.selectionChange.emit(this.selection);
751 this.onRowSelect.emit({ originalEvent: event.originalEvent, index: event.rowIndex, data: rowData, type: 'radiobutton' });
752 if (this.dataKey) {
753 this.selectionKeys = {};
754 this.selectionKeys[String(ObjectUtils.resolveFieldData(rowData, this.dataKey))] = 1;
755 }
756 }
757 else {
758 this._selection = null;
759 this.selectionChange.emit(this.selection);
760 this.onRowUnselect.emit({ originalEvent: event.originalEvent, index: event.rowIndex, data: rowData, type: 'radiobutton' });
761 }
762 this.tableService.onSelectionChange();
763 if (this.isStateful()) {
764 this.saveState();
765 }
766 }
767 toggleRowWithCheckbox(event, rowData) {
768 this.selection = this.selection || [];
769 let selected = this.isSelected(rowData);
770 let dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rowData, this.dataKey)) : null;
771 this.preventSelectionSetterPropagation = true;
772 if (selected) {
773 let selectionIndex = this.findIndexInSelection(rowData);
774 this._selection = this.selection.filter((val, i) => i != selectionIndex);
775 this.selectionChange.emit(this.selection);
776 this.onRowUnselect.emit({ originalEvent: event.originalEvent, index: event.rowIndex, data: rowData, type: 'checkbox' });
777 if (dataKeyValue) {
778 delete this.selectionKeys[dataKeyValue];
779 }
780 }
781 else {
782 this._selection = this.selection ? [...this.selection, rowData] : [rowData];
783 this.selectionChange.emit(this.selection);
784 this.onRowSelect.emit({ originalEvent: event.originalEvent, index: event.rowIndex, data: rowData, type: 'checkbox' });
785 if (dataKeyValue) {
786 this.selectionKeys[dataKeyValue] = 1;
787 }
788 }
789 this.tableService.onSelectionChange();
790 if (this.isStateful()) {
791 this.saveState();
792 }
793 }
794 toggleRowsWithCheckbox(event, check) {
795 this._selection = check ? this.filteredValue ? this.filteredValue.slice() : this.value.slice() : [];
796 this.preventSelectionSetterPropagation = true;
797 this.updateSelectionKeys();
798 this.selectionChange.emit(this._selection);
799 this.tableService.onSelectionChange();
800 this.onHeaderCheckboxToggle.emit({ originalEvent: event, checked: check });
801 if (this.isStateful()) {
802 this.saveState();
803 }
804 }
805 equals(data1, data2) {
806 return this.compareSelectionBy === 'equals' ? (data1 === data2) : ObjectUtils.equals(data1, data2, this.dataKey);
807 }
808 filter(value, field, matchMode) {
809 if (this.filterTimeout) {
810 clearTimeout(this.filterTimeout);
811 }
812 if (!this.isFilterBlank(value)) {
813 this.filters[field] = { value: value, matchMode: matchMode };
814 }
815 else if (this.filters[field]) {
816 delete this.filters[field];
817 }
818 this.filterTimeout = setTimeout(() => {
819 this._filter();
820 this.filterTimeout = null;
821 }, this.filterDelay);
822 this.anchorRowIndex = null;
823 }
824 filterGlobal(value, matchMode) {
825 this.filter(value, 'global', matchMode);
826 }
827 isFilterBlank(filter) {
828 if (filter !== null && filter !== undefined) {
829 if ((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0))
830 return true;
831 else
832 return false;
833 }
834 return true;
835 }
836 _filter() {
837 if (!this.restoringFilter) {
838 this.first = 0;
839 this.firstChange.emit(this.first);
840 }
841 if (this.lazy) {
842 this.onLazyLoad.emit(this.createLazyLoadMetadata());
843 }
844 else {
845 if (!this.value) {
846 return;
847 }
848 if (!this.hasFilter()) {
849 this.filteredValue = null;
850 if (this.paginator) {
851 this.totalRecords = this.value ? this.value.length : 0;
852 }
853 }
854 else {
855 let globalFilterFieldsArray;
856 if (this.filters['global']) {
857 if (!this.columns && !this.globalFilterFields)
858 throw new Error('Global filtering requires dynamic columns or globalFilterFields to be defined.');
859 else
860 globalFilterFieldsArray = this.globalFilterFields || this.columns;
861 }
862 this.filteredValue = [];
863 for (let i = 0; i < this.value.length; i++) {
864 let localMatch = true;
865 let globalMatch = false;
866 let localFiltered = false;
867 for (let prop in this.filters) {
868 if (this.filters.hasOwnProperty(prop) && prop !== 'global') {
869 localFiltered = true;
870 let filterMeta = this.filters[prop];
871 let filterField = prop;
872 let filterValue = filterMeta.value;
873 let filterMatchMode = filterMeta.matchMode || 'startsWith';
874 let dataFieldValue = ObjectUtils.resolveFieldData(this.value[i], filterField);
875 let filterConstraint = FilterUtils[filterMatchMode];
876 if (!filterConstraint(dataFieldValue, filterValue, this.filterLocale)) {
877 localMatch = false;
878 }
879 if (!localMatch) {
880 break;
881 }
882 }
883 }
884 if (this.filters['global'] && !globalMatch && globalFilterFieldsArray) {
885 for (let j = 0; j < globalFilterFieldsArray.length; j++) {
886 let globalFilterField = globalFilterFieldsArray[j].field || globalFilterFieldsArray[j];
887 globalMatch = FilterUtils[this.filters['global'].matchMode](ObjectUtils.resolveFieldData(this.value[i], globalFilterField), this.filters['global'].value, this.filterLocale);
888 if (globalMatch) {
889 break;
890 }
891 }
892 }
893 let matches;
894 if (this.filters['global']) {
895 matches = localFiltered ? (localFiltered && localMatch && globalMatch) : globalMatch;
896 }
897 else {
898 matches = localFiltered && localMatch;
899 }
900 if (matches) {
901 this.filteredValue.push(this.value[i]);
902 }
903 }
904 if (this.filteredValue.length === this.value.length) {
905 this.filteredValue = null;
906 }
907 if (this.paginator) {
908 this.totalRecords = this.filteredValue ? this.filteredValue.length : this.value ? this.value.length : 0;
909 }
910 }
911 }
912 this.onFilter.emit({
913 filters: this.filters,
914 filteredValue: this.filteredValue || this.value
915 });
916 this.tableService.onValueChange(this.value);
917 if (this.isStateful() && !this.restoringFilter) {
918 this.saveState();
919 }
920 if (this.restoringFilter) {
921 this.restoringFilter = false;
922 }
923 this.cd.markForCheck();
924 if (this.scrollable) {
925 this.resetScrollTop();
926 }
927 }
928 hasFilter() {
929 let empty = true;
930 for (let prop in this.filters) {
931 if (this.filters.hasOwnProperty(prop)) {
932 empty = false;
933 break;
934 }
935 }
936 return !empty;
937 }
938 createLazyLoadMetadata() {
939 return {
940 first: this.first,
941 rows: this.rows,
942 sortField: this.sortField,
943 sortOrder: this.sortOrder,
944 filters: this.filters,
945 globalFilter: this.filters && this.filters['global'] ? this.filters['global'].value : null,
946 multiSortMeta: this.multiSortMeta
947 };
948 }
949 clear() {
950 this._sortField = null;
951 this._sortOrder = this.defaultSortOrder;
952 this._multiSortMeta = null;
953 this.tableService.onSort(null);
954 this.filteredValue = null;
955 this.filters = {};
956 this.first = 0;
957 this.firstChange.emit(this.first);
958 if (this.lazy) {
959 this.onLazyLoad.emit(this.createLazyLoadMetadata());
960 }
961 else {
962 this.totalRecords = (this._value ? this._value.length : 0);
963 }
964 }
965 reset() {
966 console.warn("reset function is deprecated, use clear instead.");
967 this.clear();
968 }
969 exportCSV(options) {
970 let data;
971 let csv = '';
972 let columns = this.frozenColumns ? [...this.frozenColumns, ...this.columns] : this.columns;
973 if (options && options.selectionOnly) {
974 data = this.selection || [];
975 }
976 else {
977 data = this.filteredValue || this.value;
978 if (this.frozenValue) {
979 data = data ? [...this.frozenValue, ...data] : this.frozenValue;
980 }
981 }
982 //headers
983 for (let i = 0; i < columns.length; i++) {
984 let column = columns[i];
985 if (column.exportable !== false && column.field) {
986 csv += '"' + (column.header || column.field) + '"';
987 if (i < (columns.length - 1)) {
988 csv += this.csvSeparator;
989 }
990 }
991 }
992 //body
993 data.forEach((record, i) => {
994 csv += '\n';
995 for (let i = 0; i < columns.length; i++) {
996 let column = columns[i];
997 if (column.exportable !== false && column.field) {
998 let cellData = ObjectUtils.resolveFieldData(record, column.field);
999 if (cellData != null) {
1000 if (this.exportFunction) {
1001 cellData = this.exportFunction({
1002 data: cellData,
1003 field: column.field
1004 });
1005 }
1006 else
1007 cellData = String(cellData).replace(/"/g, '""');
1008 }
1009 else
1010 cellData = '';
1011 csv += '"' + cellData + '"';
1012 if (i < (columns.length - 1)) {
1013 csv += this.csvSeparator;
1014 }
1015 }
1016 }
1017 });
1018 let blob = new Blob([csv], {
1019 type: 'text/csv;charset=utf-8;'
1020 });
1021 if (window.navigator.msSaveOrOpenBlob) {
1022 navigator.msSaveOrOpenBlob(blob, this.exportFilename + '.csv');
1023 }
1024 else {
1025 let link = document.createElement("a");
1026 link.style.display = 'none';
1027 document.body.appendChild(link);
1028 if (link.download !== undefined) {
1029 link.setAttribute('href', URL.createObjectURL(blob));
1030 link.setAttribute('download', this.exportFilename + '.csv');
1031 link.click();
1032 }
1033 else {
1034 csv = 'data:text/csv;charset=utf-8,' + csv;
1035 window.open(encodeURI(csv));
1036 }
1037 document.body.removeChild(link);
1038 }
1039 }
1040 resetScrollTop() {
1041 if (this.virtualScroll)
1042 this.scrollToVirtualIndex(0);
1043 else
1044 this.scrollTo({ top: 0 });
1045 }
1046 scrollToVirtualIndex(index) {
1047 if (this.scrollableViewChild) {
1048 this.scrollableViewChild.scrollToVirtualIndex(index);
1049 }
1050 if (this.scrollableFrozenViewChild) {
1051 this.scrollableFrozenViewChild.scrollToVirtualIndex(index);
1052 }
1053 }
1054 scrollTo(options) {
1055 if (this.scrollableViewChild) {
1056 this.scrollableViewChild.scrollTo(options);
1057 }
1058 if (this.scrollableFrozenViewChild) {
1059 this.scrollableFrozenViewChild.scrollTo(options);
1060 }
1061 }
1062 updateEditingCell(cell, data, field, index) {
1063 this.editingCell = cell;
1064 this.editingCellData = data;
1065 this.editingCellField = field;
1066 this.editingCellRowIndex = index;
1067 this.bindDocumentEditListener();
1068 }
1069 isEditingCellValid() {
1070 return (this.editingCell && DomHandler.find(this.editingCell, '.ng-invalid.ng-dirty').length === 0);
1071 }
1072 bindDocumentEditListener() {
1073 if (!this.documentEditListener) {
1074 this.documentEditListener = (event) => {
1075 if (this.editingCell && !this.editingCellClick && this.isEditingCellValid()) {
1076 DomHandler.removeClass(this.editingCell, 'p-cell-editing');
1077 this.editingCell = null;
1078 this.onEditComplete.emit({ field: this.editingCellField, data: this.editingCellData, originalEvent: event, index: this.editingCellRowIndex });
1079 this.editingCellField = null;
1080 this.editingCellData = null;
1081 this.editingCellRowIndex = null;
1082 this.unbindDocumentEditListener();
1083 this.cd.markForCheck();
1084 }
1085 this.editingCellClick = false;
1086 };
1087 document.addEventListener('click', this.documentEditListener);
1088 }
1089 }
1090 unbindDocumentEditListener() {
1091 if (this.documentEditListener) {
1092 document.removeEventListener('click', this.documentEditListener);
1093 this.documentEditListener = null;
1094 }
1095 }
1096 initRowEdit(rowData) {
1097 let dataKeyValue = String(ObjectUtils.resolveFieldData(rowData, this.dataKey));
1098 this.editingRowKeys[dataKeyValue] = true;
1099 }
1100 saveRowEdit(rowData, rowElement) {
1101 if (DomHandler.find(rowElement, '.ng-invalid.ng-dirty').length === 0) {
1102 let dataKeyValue = String(ObjectUtils.resolveFieldData(rowData, this.dataKey));
1103 delete this.editingRowKeys[dataKeyValue];
1104 }
1105 }
1106 cancelRowEdit(rowData) {
1107 let dataKeyValue = String(ObjectUtils.resolveFieldData(rowData, this.dataKey));
1108 delete this.editingRowKeys[dataKeyValue];
1109 }
1110 toggleRow(rowData, event) {
1111 if (!this.dataKey) {
1112 throw new Error('dataKey must be defined to use row expansion');
1113 }
1114 let dataKeyValue = String(ObjectUtils.resolveFieldData(rowData, this.dataKey));
1115 if (this.expandedRowKeys[dataKeyValue] != null) {
1116 delete this.expandedRowKeys[dataKeyValue];
1117 this.onRowCollapse.emit({
1118 originalEvent: event,
1119 data: rowData
1120 });
1121 }
1122 else {
1123 if (this.rowExpandMode === 'single') {
1124 this.expandedRowKeys = {};
1125 }
1126 this.expandedRowKeys[dataKeyValue] = true;
1127 this.onRowExpand.emit({
1128 originalEvent: event,
1129 data: rowData
1130 });
1131 }
1132 if (event) {
1133 event.preventDefault();
1134 }
1135 if (this.isStateful()) {
1136 this.saveState();
1137 }
1138 }
1139 isRowExpanded(rowData) {
1140 return this.expandedRowKeys[String(ObjectUtils.resolveFieldData(rowData, this.dataKey))] === true;
1141 }
1142 isRowEditing(rowData) {
1143 return this.editingRowKeys[String(ObjectUtils.resolveFieldData(rowData, this.dataKey))] === true;
1144 }
1145 isSingleSelectionMode() {
1146 return this.selectionMode === 'single';
1147 }
1148 isMultipleSelectionMode() {
1149 return this.selectionMode === 'multiple';
1150 }
1151 onColumnResizeBegin(event) {
1152 let containerLeft = DomHandler.getOffset(this.containerViewChild.nativeElement).left;
1153 this.lastResizerHelperX = (event.pageX - containerLeft + this.containerViewChild.nativeElement.scrollLeft);
1154 this.onColumnResize(event);
1155 event.preventDefault();
1156 }
1157 onColumnResize(event) {
1158 let containerLeft = DomHandler.getOffset(this.containerViewChild.nativeElement).left;
1159 DomHandler.addClass(this.containerViewChild.nativeElement, 'p-unselectable-text');
1160 this.resizeHelperViewChild.nativeElement.style.height = this.containerViewChild.nativeElement.offsetHeight + 'px';
1161 this.resizeHelperViewChild.nativeElement.style.top = 0 + 'px';
1162 this.resizeHelperViewChild.nativeElement.style.left = (event.pageX - containerLeft + this.containerViewChild.nativeElement.scrollLeft) + 'px';
1163 this.resizeHelperViewChild.nativeElement.style.display = 'block';
1164 }
1165 onColumnResizeEnd(event, column) {
1166 let delta = this.resizeHelperViewChild.nativeElement.offsetLeft - this.lastResizerHelperX;
1167 let columnWidth = column.offsetWidth;
1168 let minWidth = parseInt(column.style.minWidth || 15);
1169 if (columnWidth + delta < minWidth) {
1170 delta = minWidth - columnWidth;
1171 }
1172 const newColumnWidth = columnWidth + delta;
1173 if (newColumnWidth >= minWidth) {
1174 if (this.columnResizeMode === 'fit') {
1175 let nextColumn = column.nextElementSibling;
1176 while (!nextColumn.offsetParent) {
1177 nextColumn = nextColumn.nextElementSibling;
1178 }
1179 if (nextColumn) {
1180 let nextColumnWidth = nextColumn.offsetWidth - delta;
1181 let nextColumnMinWidth = nextColumn.style.minWidth || 15;
1182 if (newColumnWidth > 15 && nextColumnWidth > parseInt(nextColumnMinWidth)) {
1183 if (this.scrollable) {
1184 let scrollableView = this.findParentScrollableView(column);
1185 let scrollableBodyTable = DomHandler.findSingle(scrollableView, '.p-datatable-scrollable-body table') || DomHandler.findSingle(scrollableView, '.p-datatable-scrollable-body table');
1186 let scrollableHeaderTable = DomHandler.findSingle(scrollableView, 'table.p-datatable-scrollable-header-table');
1187 let scrollableFooterTable = DomHandler.findSingle(scrollableView, 'table.p-datatable-scrollable-footer-table');
1188 let resizeColumnIndex = DomHandler.index(column);
1189 this.resizeColGroup(scrollableHeaderTable, resizeColumnIndex, newColumnWidth, nextColumnWidth);
1190 this.resizeColGroup(scrollableBodyTable, resizeColumnIndex, newColumnWidth, nextColumnWidth);
1191 this.resizeColGroup(scrollableFooterTable, resizeColumnIndex, newColumnWidth, nextColumnWidth);
1192 }
1193 else {
1194 column.style.width = newColumnWidth + 'px';
1195 if (nextColumn) {
1196 nextColumn.style.width = nextColumnWidth + 'px';
1197 }
1198 }
1199 }
1200 }
1201 }
1202 else if (this.columnResizeMode === 'expand') {
1203 if (newColumnWidth >= minWidth) {
1204 if (this.scrollable) {
1205 this.setScrollableItemsWidthOnExpandResize(column, newColumnWidth, delta);
1206 }
1207 else {
1208 this.tableViewChild.nativeElement.style.width = this.tableViewChild.nativeElement.offsetWidth + delta + 'px';
1209 column.style.width = newColumnWidth + 'px';
1210 let containerWidth = this.tableViewChild.nativeElement.style.width;
1211 this.containerViewChild.nativeElement.style.width = containerWidth + 'px';
1212 }
1213 }
1214 }
1215 this.onColResize.emit({
1216 element: column,
1217 delta: delta
1218 });
1219 if (this.isStateful()) {
1220 this.saveState();
1221 }
1222 }
1223 this.resizeHelperViewChild.nativeElement.style.display = 'none';
1224 DomHandler.removeClass(this.containerViewChild.nativeElement, 'p-unselectable-text');
1225 }
1226 setScrollableItemsWidthOnExpandResize(column, newColumnWidth, delta) {
1227 let scrollableView = column ? this.findParentScrollableView(column) : this.containerViewChild.nativeElement;
1228 let scrollableBody = DomHandler.findSingle(scrollableView, '.p-datatable-scrollable-body') || DomHandler.findSingle(scrollableView, 'cdk-virtual-scroll-viewport');
1229 let scrollableHeader = DomHandler.findSingle(scrollableView, '.p-datatable-scrollable-header');
1230 let scrollableFooter = DomHandler.findSingle(scrollableView, '.p-datatable-scrollable-footer');
1231 let scrollableBodyTable = DomHandler.findSingle(scrollableBody, '.p-datatable-scrollable-body table') || DomHandler.findSingle(scrollableView, 'cdk-virtual-scroll-viewport table');
1232 let scrollableHeaderTable = DomHandler.findSingle(scrollableHeader, 'table.p-datatable-scrollable-header-table');
1233 let scrollableFooterTable = DomHandler.findSingle(scrollableFooter, 'table.p-datatable-scrollable-footer-table');
1234 const scrollableBodyTableWidth = column ? scrollableBodyTable.offsetWidth + delta : newColumnWidth;
1235 const scrollableHeaderTableWidth = column ? scrollableHeaderTable.offsetWidth + delta : newColumnWidth;
1236 const isContainerInViewport = this.containerViewChild.nativeElement.offsetWidth >= scrollableBodyTableWidth;
1237 let setWidth = (container, table, width, isContainerInViewport) => {
1238 if (container && table) {
1239 container.style.width = isContainerInViewport ? width + DomHandler.calculateScrollbarWidth(scrollableBody) + 'px' : 'auto';
1240 table.style.width = width + 'px';
1241 }
1242 };
1243 setWidth(scrollableBody, scrollableBodyTable, scrollableBodyTableWidth, isContainerInViewport);
1244 setWidth(scrollableHeader, scrollableHeaderTable, scrollableHeaderTableWidth, isContainerInViewport);
1245 setWidth(scrollableFooter, scrollableFooterTable, scrollableHeaderTableWidth, isContainerInViewport);
1246 if (column) {
1247 let resizeColumnIndex = DomHandler.index(column);
1248 this.resizeColGroup(scrollableHeaderTable, resizeColumnIndex, newColumnWidth, null);
1249 this.resizeColGroup(scrollableBodyTable, resizeColumnIndex, newColumnWidth, null);
1250 this.resizeColGroup(scrollableFooterTable, resizeColumnIndex, newColumnWidth, null);
1251 }
1252 }
1253 findParentScrollableView(column) {
1254 if (column) {
1255 let parent = column.parentElement;
1256 while (parent && !DomHandler.hasClass(parent, 'p-datatable-scrollable-view')) {
1257 parent = parent.parentElement;
1258 }
1259 return parent;
1260 }
1261 else {
1262 return null;
1263 }
1264 }
1265 resizeColGroup(table, resizeColumnIndex, newColumnWidth, nextColumnWidth) {
1266 if (table) {
1267 let colGroup = table.children[0].nodeName === 'COLGROUP' ? table.children[0] : null;
1268 if (colGroup) {
1269 let col = colGroup.children[resizeColumnIndex];
1270 let nextCol = col.nextElementSibling;
1271 col.style.width = newColumnWidth + 'px';
1272 if (nextCol && nextColumnWidth) {
1273 nextCol.style.width = nextColumnWidth + 'px';
1274 }
1275 }
1276 else {
1277 throw "Scrollable tables require a colgroup to support resizable columns";
1278 }
1279 }
1280 }
1281 onColumnDragStart(event, columnElement) {
1282 this.reorderIconWidth = DomHandler.getHiddenElementOuterWidth(this.reorderIndicatorUpViewChild.nativeElement);
1283 this.reorderIconHeight = DomHandler.getHiddenElementOuterHeight(this.reorderIndicatorDownViewChild.nativeElement);
1284 this.draggedColumn = columnElement;
1285 event.dataTransfer.setData('text', 'b'); // For firefox
1286 }
1287 onColumnDragEnter(event, dropHeader) {
1288 if (this.reorderableColumns && this.draggedColumn && dropHeader) {
1289 event.preventDefault();
1290 let containerOffset = DomHandler.getOffset(this.containerViewChild.nativeElement);
1291 let dropHeaderOffset = DomHandler.getOffset(dropHeader);
1292 if (this.draggedColumn != dropHeader) {
1293 let dragIndex = DomHandler.indexWithinGroup(this.draggedColumn, 'preorderablecolumn');
1294 let dropIndex = DomHandler.indexWithinGroup(dropHeader, 'preorderablecolumn');
1295 let targetLeft = dropHeaderOffset.left - containerOffset.left;
1296 let targetTop = containerOffset.top - dropHeaderOffset.top;
1297 let columnCenter = dropHeaderOffset.left + dropHeader.offsetWidth / 2;
1298 this.reorderIndicatorUpViewChild.nativeElement.style.top = dropHeaderOffset.top - containerOffset.top - (this.reorderIconHeight - 1) + 'px';
1299 this.reorderIndicatorDownViewChild.nativeElement.style.top = dropHeaderOffset.top - containerOffset.top + dropHeader.offsetHeight + 'px';
1300 if (event.pageX > columnCenter) {
1301 this.reorderIndicatorUpViewChild.nativeElement.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.reorderIconWidth / 2)) + 'px';
1302 this.reorderIndicatorDownViewChild.nativeElement.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.reorderIconWidth / 2)) + 'px';
1303 this.dropPosition = 1;
1304 }
1305 else {
1306 this.reorderIndicatorUpViewChild.nativeElement.style.left = (targetLeft - Math.ceil(this.reorderIconWidth / 2)) + 'px';
1307 this.reorderIndicatorDownViewChild.nativeElement.style.left = (targetLeft - Math.ceil(this.reorderIconWidth / 2)) + 'px';
1308 this.dropPosition = -1;
1309 }
1310 if ((dropIndex - dragIndex === 1 && this.dropPosition === -1) || (dropIndex - dragIndex === -1 && this.dropPosition === 1)) {
1311 this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none';
1312 this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none';
1313 }
1314 else {
1315 this.reorderIndicatorUpViewChild.nativeElement.style.display = 'block';
1316 this.reorderIndicatorDownViewChild.nativeElement.style.display = 'block';
1317 }
1318 }
1319 else {
1320 event.dataTransfer.dropEffect = 'none';
1321 }
1322 }
1323 }
1324 onColumnDragLeave(event) {
1325 if (this.reorderableColumns && this.draggedColumn) {
1326 event.preventDefault();
1327 this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none';
1328 this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none';
1329 }
1330 }
1331 onColumnDrop(event, dropColumn) {
1332 event.preventDefault();
1333 if (this.draggedColumn) {
1334 let dragIndex = DomHandler.indexWithinGroup(this.draggedColumn, 'preorderablecolumn');
1335 let dropIndex = DomHandler.indexWithinGroup(dropColumn, 'preorderablecolumn');
1336 let allowDrop = (dragIndex != dropIndex);
1337 if (allowDrop && ((dropIndex - dragIndex == 1 && this.dropPosition === -1) || (dragIndex - dropIndex == 1 && this.dropPosition === 1))) {
1338 allowDrop = false;
1339 }
1340 if (allowDrop && ((dropIndex < dragIndex && this.dropPosition === 1))) {
1341 dropIndex = dropIndex + 1;
1342 }
1343 if (allowDrop && ((dropIndex > dragIndex && this.dropPosition === -1))) {
1344 dropIndex = dropIndex - 1;
1345 }
1346 if (allowDrop) {
1347 ObjectUtils.reorderArray(this.columns, dragIndex, dropIndex);
1348 this.onColReorder.emit({
1349 dragIndex: dragIndex,
1350 dropIndex: dropIndex,
1351 columns: this.columns
1352 });
1353 if (this.isStateful()) {
1354 this.zone.runOutsideAngular(() => {
1355 setTimeout(() => {
1356 this.saveState();
1357 });
1358 });
1359 }
1360 }
1361 this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none';
1362 this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none';
1363 this.draggedColumn.draggable = false;
1364 this.draggedColumn = null;
1365 this.dropPosition = null;
1366 }
1367 }
1368 onRowDragStart(event, index) {
1369 this.rowDragging = true;
1370 this.draggedRowIndex = index;
1371 event.dataTransfer.setData('text', 'b'); // For firefox
1372 }
1373 onRowDragOver(event, index, rowElement) {
1374 if (this.rowDragging && this.draggedRowIndex !== index) {
1375 let rowY = DomHandler.getOffset(rowElement).top + DomHandler.getWindowScrollTop();
1376 let pageY = event.pageY;
1377 let rowMidY = rowY + DomHandler.getOuterHeight(rowElement) / 2;
1378 let prevRowElement = rowElement.previousElementSibling;
1379 if (pageY < rowMidY) {
1380 DomHandler.removeClass(rowElement, 'p-datatable-dragpoint-bottom');
1381 this.droppedRowIndex = index;
1382 if (prevRowElement)
1383 DomHandler.addClass(prevRowElement, 'p-datatable-dragpoint-bottom');
1384 else
1385 DomHandler.addClass(rowElement, 'p-datatable-dragpoint-top');
1386 }
1387 else {
1388 if (prevRowElement)
1389 DomHandler.removeClass(prevRowElement, 'p-datatable-dragpoint-bottom');
1390 else
1391 DomHandler.addClass(rowElement, 'p-datatable-dragpoint-top');
1392 this.droppedRowIndex = index + 1;
1393 DomHandler.addClass(rowElement, 'p-datatable-dragpoint-bottom');
1394 }
1395 }
1396 }
1397 onRowDragLeave(event, rowElement) {
1398 let prevRowElement = rowElement.previousElementSibling;
1399 if (prevRowElement) {
1400 DomHandler.removeClass(prevRowElement, 'p-datatable-dragpoint-bottom');
1401 }
1402 DomHandler.removeClass(rowElement, 'p-datatable-dragpoint-bottom');
1403 DomHandler.removeClass(rowElement, 'p-datatable-dragpoint-top');
1404 }
1405 onRowDragEnd(event) {
1406 this.rowDragging = false;
1407 this.draggedRowIndex = null;
1408 this.droppedRowIndex = null;
1409 }
1410 onRowDrop(event, rowElement) {
1411 if (this.droppedRowIndex != null) {
1412 let dropIndex = (this.draggedRowIndex > this.droppedRowIndex) ? this.droppedRowIndex : (this.droppedRowIndex === 0) ? 0 : this.droppedRowIndex - 1;
1413 ObjectUtils.reorderArray(this.value, this.draggedRowIndex, dropIndex);
1414 this.onRowReorder.emit({
1415 dragIndex: this.draggedRowIndex,
1416 dropIndex: dropIndex
1417 });
1418 }
1419 //cleanup
1420 this.onRowDragLeave(event, rowElement);
1421 this.onRowDragEnd(event);
1422 }
1423 isEmpty() {
1424 let data = this.filteredValue || this.value;
1425 return data == null || data.length == 0;
1426 }
1427 getBlockableElement() {
1428 return this.el.nativeElement.children[0];
1429 }
1430 getStorage() {
1431 switch (this.stateStorage) {
1432 case 'local':
1433 return window.localStorage;
1434 case 'session':
1435 return window.sessionStorage;
1436 default:
1437 throw new Error(this.stateStorage + ' is not a valid value for the state storage, supported values are "local" and "session".');
1438 }
1439 }
1440 isStateful() {
1441 return this.stateKey != null;
1442 }
1443 saveState() {
1444 const storage = this.getStorage();
1445 let state = {};
1446 if (this.paginator) {
1447 state.first = this.first;
1448 state.rows = this.rows;
1449 }
1450 if (this.sortField) {
1451 state.sortField = this.sortField;
1452 state.sortOrder = this.sortOrder;
1453 }
1454 if (this.multiSortMeta) {
1455 state.multiSortMeta = this.multiSortMeta;
1456 }
1457 if (this.hasFilter()) {
1458 state.filters = this.filters;
1459 }
1460 if (this.resizableColumns) {
1461 this.saveColumnWidths(state);
1462 }
1463 if (this.reorderableColumns) {
1464 this.saveColumnOrder(state);
1465 }
1466 if (this.selection) {
1467 state.selection = this.selection;
1468 }
1469 if (Object.keys(this.expandedRowKeys).length) {
1470 state.expandedRowKeys = this.expandedRowKeys;
1471 }
1472 if (Object.keys(state).length) {
1473 storage.setItem(this.stateKey, JSON.stringify(state));
1474 }
1475 this.onStateSave.emit(state);
1476 }
1477 clearState() {
1478 const storage = this.getStorage();
1479 if (this.stateKey) {
1480 storage.removeItem(this.stateKey);
1481 }
1482 }
1483 restoreState() {
1484 const storage = this.getStorage();
1485 const stateString = storage.getItem(this.stateKey);
1486 if (stateString) {
1487 let state = JSON.parse(stateString);
1488 if (this.paginator) {
1489 if (this.first !== undefined) {
1490 this.first = state.first;
1491 this.firstChange.emit(this.first);
1492 }
1493 if (this.rows !== undefined) {
1494 this.rows = state.rows;
1495 this.rowsChange.emit(this.rows);
1496 }
1497 }
1498 if (state.sortField) {
1499 this.restoringSort = true;
1500 this._sortField = state.sortField;
1501 this._sortOrder = state.sortOrder;
1502 }
1503 if (state.multiSortMeta) {
1504 this.restoringSort = true;
1505 this._multiSortMeta = state.multiSortMeta;
1506 }
1507 if (state.filters) {
1508 this.restoringFilter = true;
1509 this.filters = state.filters;
1510 }
1511 if (this.resizableColumns) {
1512 this.columnWidthsState = state.columnWidths;
1513 this.tableWidthState = state.tableWidth;
1514 }
1515 if (state.expandedRowKeys) {
1516 this.expandedRowKeys = state.expandedRowKeys;
1517 }
1518 if (state.selection) {
1519 Promise.resolve(null).then(() => this.selectionChange.emit(state.selection));
1520 }
1521 this.stateRestored = true;
1522 this.onStateRestore.emit(state);
1523 }
1524 }
1525 saveColumnWidths(state) {
1526 let widths = [];
1527 let headers = DomHandler.find(this.containerViewChild.nativeElement, '.p-datatable-thead > tr:first-child > th');
1528 headers.map(header => widths.push(DomHandler.getOuterWidth(header)));
1529 state.columnWidths = widths.join(',');
1530 if (this.columnResizeMode === 'expand') {
1531 state.tableWidth = this.scrollable ? DomHandler.findSingle(this.containerViewChild.nativeElement, '.p-datatable-scrollable-header-table').style.width :
1532 DomHandler.getOuterWidth(this.tableViewChild.nativeElement) + 'px';
1533 }
1534 }
1535 restoreColumnWidths() {
1536 if (this.columnWidthsState) {
1537 let widths = this.columnWidthsState.split(',');
1538 if (this.columnResizeMode === 'expand' && this.tableWidthState) {
1539 if (this.scrollable) {
1540 this.setScrollableItemsWidthOnExpandResize(null, this.tableWidthState, 0);
1541 }
1542 else {
1543 this.tableViewChild.nativeElement.style.width = this.tableWidthState;
1544 this.containerViewChild.nativeElement.style.width = this.tableWidthState;
1545 }
1546 }
1547 if (this.scrollable) {
1548 let headerCols = DomHandler.find(this.containerViewChild.nativeElement, '.p-datatable-scrollable-header-table > colgroup > col');
1549 let bodyCols = DomHandler.find(this.containerViewChild.nativeElement, '.p-datatable-scrollable-body table > colgroup > col');
1550 headerCols.map((col, index) => col.style.width = widths[index] + 'px');
1551 bodyCols.map((col, index) => col.style.width = widths[index] + 'px');
1552 }
1553 else {
1554 let headers = DomHandler.find(this.tableViewChild.nativeElement, '.p-datatable-thead > tr:first-child > th');
1555 headers.map((header, index) => header.style.width = widths[index] + 'px');
1556 }
1557 }
1558 }
1559 saveColumnOrder(state) {
1560 if (this.columns) {
1561 let columnOrder = [];
1562 this.columns.map(column => {
1563 columnOrder.push(column.field || column.key);
1564 });
1565 state.columnOrder = columnOrder;
1566 }
1567 }
1568 restoreColumnOrder() {
1569 const storage = this.getStorage();
1570 const stateString = storage.getItem(this.stateKey);
1571 if (stateString) {
1572 let state = JSON.parse(stateString);
1573 let columnOrder = state.columnOrder;
1574 if (columnOrder) {
1575 let reorderedColumns = [];
1576 columnOrder.map(key => reorderedColumns.push(this.findColumnByKey(key)));
1577 this.columnOrderStateRestored = true;
1578 this.columns = reorderedColumns;
1579 }
1580 }
1581 }
1582 findColumnByKey(key) {
1583 if (this.columns) {
1584 for (let col of this.columns) {
1585 if (col.key === key || col.field === key)
1586 return col;
1587 else
1588 continue;
1589 }
1590 }
1591 else {
1592 return null;
1593 }
1594 }
1595 ngOnDestroy() {
1596 this.unbindDocumentEditListener();
1597 this.editingCell = null;
1598 this.initialized = null;
1599 }
1600}
1601Table.decorators = [
1602 { type: Component, args: [{
1603 selector: 'p-table',
1604 template: `
1605 <div #container [ngStyle]="style" [class]="styleClass" data-scrollselectors=".p-datatable-scrollable-body, .p-datatable-unfrozen-view .p-datatable-scrollable-body"
1606 [ngClass]="{'p-datatable p-component': true,
1607 'p-datatable-hoverable-rows': (rowHover||selectionMode),
1608 'p-datatable-auto-layout': autoLayout,
1609 'p-datatable-resizable': resizableColumns,
1610 'p-datatable-resizable-fit': (resizableColumns && columnResizeMode === 'fit'),
1611 'p-datatable-scrollable': scrollable,
1612 'p-datatable-flex-scrollable': (scrollable && scrollHeight === 'flex'),
1613 'p-datatable-responsive': responsive}">
1614 <div class="p-datatable-loading-overlay p-component-overlay" *ngIf="loading && showLoader">
1615 <i [class]="'p-datatable-loading-icon pi-spin ' + loadingIcon"></i>
1616 </div>
1617 <div *ngIf="captionTemplate" class="p-datatable-header">
1618 <ng-container *ngTemplateOutlet="captionTemplate"></ng-container>
1619 </div>
1620 <p-paginator [rows]="rows" [first]="first" [totalRecords]="totalRecords" [pageLinkSize]="pageLinks" styleClass="p-paginator-top" [alwaysShow]="alwaysShowPaginator"
1621 (onPageChange)="onPageChange($event)" [rowsPerPageOptions]="rowsPerPageOptions" *ngIf="paginator && (paginatorPosition === 'top' || paginatorPosition =='both')"
1622 [templateLeft]="paginatorLeftTemplate" [templateRight]="paginatorRightTemplate" [dropdownAppendTo]="paginatorDropdownAppendTo" [dropdownScrollHeight]="paginatorDropdownScrollHeight"
1623 [currentPageReportTemplate]="currentPageReportTemplate" [showCurrentPageReport]="showCurrentPageReport" [showJumpToPageDropdown]="showJumpToPageDropdown" [showPageLinks]="showPageLinks"></p-paginator>
1624
1625 <div class="p-datatable-wrapper" *ngIf="!scrollable">
1626 <table role="grid" #table [ngClass]="tableStyleClass" [ngStyle]="tableStyle">
1627 <ng-container *ngTemplateOutlet="colGroupTemplate; context {$implicit: columns}"></ng-container>
1628 <thead class="p-datatable-thead">
1629 <ng-container *ngTemplateOutlet="headerTemplate; context: {$implicit: columns}"></ng-container>
1630 </thead>
1631 <tbody class="p-datatable-tbody" [pTableBody]="columns" [pTableBodyTemplate]="bodyTemplate"></tbody>
1632 <tfoot *ngIf="footerTemplate" class="p-datatable-tfoot">
1633 <ng-container *ngTemplateOutlet="footerTemplate; context {$implicit: columns}"></ng-container>
1634 </tfoot>
1635 </table>
1636 </div>
1637
1638 <div class="p-datatable-scrollable-wrapper" *ngIf="scrollable">
1639 <div class="p-datatable-scrollable-view p-datatable-frozen-view" *ngIf="frozenColumns||frozenBodyTemplate" #scrollableFrozenView [pScrollableView]="frozenColumns" [frozen]="true" [ngStyle]="{width: frozenWidth}" [scrollHeight]="scrollHeight"></div>
1640 <div class="p-datatable-scrollable-view" #scrollableView [pScrollableView]="columns" [frozen]="false" [scrollHeight]="scrollHeight" [ngStyle]="{left: frozenWidth, width: 'calc(100% - '+frozenWidth+')'}"></div>
1641 </div>
1642
1643 <p-paginator [rows]="rows" [first]="first" [totalRecords]="totalRecords" [pageLinkSize]="pageLinks" styleClass="p-paginator-bottom" [alwaysShow]="alwaysShowPaginator"
1644 (onPageChange)="onPageChange($event)" [rowsPerPageOptions]="rowsPerPageOptions" *ngIf="paginator && (paginatorPosition === 'bottom' || paginatorPosition =='both')"
1645 [templateLeft]="paginatorLeftTemplate" [templateRight]="paginatorRightTemplate" [dropdownAppendTo]="paginatorDropdownAppendTo" [dropdownScrollHeight]="paginatorDropdownScrollHeight"
1646 [currentPageReportTemplate]="currentPageReportTemplate" [showCurrentPageReport]="showCurrentPageReport" [showJumpToPageDropdown]="showJumpToPageDropdown" [showPageLinks]="showPageLinks"></p-paginator>
1647
1648 <div *ngIf="summaryTemplate" class="p-datatable-footer">
1649 <ng-container *ngTemplateOutlet="summaryTemplate"></ng-container>
1650 </div>
1651
1652 <div #resizeHelper class="p-column-resizer-helper" style="display:none" *ngIf="resizableColumns"></div>
1653 <span #reorderIndicatorUp class="pi pi-arrow-down p-datatable-reorder-indicator-up" style="display:none" *ngIf="reorderableColumns"></span>
1654 <span #reorderIndicatorDown class="pi pi-arrow-up p-datatable-reorder-indicator-down" style="display:none" *ngIf="reorderableColumns"></span>
1655 </div>
1656 `,
1657 providers: [TableService],
1658 changeDetection: ChangeDetectionStrategy.Default,
1659 encapsulation: ViewEncapsulation.None,
1660 styles: [".p-datatable{position:relative}.p-datatable table{border-collapse:collapse;table-layout:fixed;width:100%}.p-datatable .p-sortable-column{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;cursor:pointer;user-select:none}.p-datatable .p-sortable-column .p-column-title,.p-datatable .p-sortable-column .p-sortable-column-badge,.p-datatable .p-sortable-column .p-sortable-column-icon{vertical-align:middle}.p-datatable .p-sortable-column .p-sortable-column-badge{-ms-flex-align:center;-ms-flex-pack:center;align-items:center;display:-ms-inline-flexbox;display:inline-flex;justify-content:center}.p-datatable-auto-layout>.p-datatable-wrapper{overflow-x:auto}.p-datatable-auto-layout>.p-datatable-wrapper>table{table-layout:auto}.p-datatable-hoverable-rows .p-selectable-row{cursor:pointer}.p-datatable-scrollable-wrapper{position:relative}.p-datatable-scrollable-footer,.p-datatable-scrollable-header{overflow:hidden}.p-datatable-scrollable-body{overflow:auto;position:relative}.p-datatable-scrollable-body>table>.p-datatable-tbody>tr:first-child>td{border-top:0}.p-datatable-virtual-table{position:absolute}.p-datatable-frozen-view .p-datatable-scrollable-body{overflow:hidden}.p-datatable-frozen-view>.p-datatable-scrollable-body>table>.p-datatable-tbody>tr>td:last-child{border-right:0}.p-datatable-unfrozen-view{position:absolute;top:0}.p-datatable-flex-scrollable,.p-datatable-flex-scrollable .p-datatable-scrollable-view,.p-datatable-flex-scrollable .p-datatable-scrollable-wrapper{-ms-flex:1;-ms-flex-direction:column;display:-ms-flexbox;display:flex;flex:1;flex-direction:column;height:100%}.p-datatable-flex-scrollable .p-datatable-scrollable-body,.p-datatable-flex-scrollable .p-datatable-virtual-scrollable-body{-ms-flex:1;flex:1}.p-datatable-resizable>.p-datatable-wrapper{overflow-x:auto}.p-datatable-resizable .p-datatable-tbody>tr>td,.p-datatable-resizable .p-datatable-tfoot>tr>td,.p-datatable-resizable .p-datatable-thead>tr>th{overflow:hidden;white-space:nowrap}.p-datatable-resizable .p-resizable-column{background-clip:padding-box;position:relative}.p-datatable-resizable-fit .p-resizable-column:last-child .p-column-resizer{display:none}.p-datatable .p-column-resizer{border:1px solid rgba(0,0,0,0);cursor:col-resize;display:block;height:100%;margin:0;padding:0;position:absolute!important;right:0;top:0;width:.5rem}.p-datatable .p-column-resizer-helper{display:none;position:absolute;width:1px;z-index:10}.p-datatable .p-row-editor-cancel,.p-datatable .p-row-editor-init,.p-datatable .p-row-editor-save,.p-datatable .p-row-toggler{-ms-flex-align:center;-ms-flex-pack:center;align-items:center;display:-ms-inline-flexbox;display:inline-flex;justify-content:center;overflow:hidden;position:relative}.p-datatable-reorder-indicator-down,.p-datatable-reorder-indicator-up{display:none;position:absolute}.p-datatable .p-datatable-loading-overlay{-ms-flex-align:center;-ms-flex-pack:center;align-items:center;display:-ms-flexbox;display:flex;justify-content:center;position:absolute;z-index:2}.p-datatable.p-datatable-responsive .p-datatable-tbody>tr>td .p-column-title{display:none}@media screen and (max-width:40em){.p-datatable.p-datatable-responsive .p-datatable-tfoot>tr>td,.p-datatable.p-datatable-responsive .p-datatable-thead>tr>th{display:none!important}.p-datatable.p-datatable-responsive .p-datatable-tbody>tr>td{border:0;clear:left;display:block;float:left;text-align:left;width:100%}.p-datatable.p-datatable-responsive .p-datatable-tbody>tr>td .p-column-title{display:inline-block;font-weight:700;margin:-.4em 1em -.4em -.4rem;min-width:30%;padding:.4rem}}"]
1661 },] }
1662];
1663Table.ctorParameters = () => [
1664 { type: ElementRef },
1665 { type: NgZone },
1666 { type: TableService },
1667 { type: ChangeDetectorRef }
1668];
1669Table.propDecorators = {
1670 frozenColumns: [{ type: Input }],
1671 frozenValue: [{ type: Input }],
1672 style: [{ type: Input }],
1673 styleClass: [{ type: Input }],
1674 tableStyle: [{ type: Input }],
1675 tableStyleClass: [{ type: Input }],
1676 paginator: [{ type: Input }],
1677 pageLinks: [{ type: Input }],
1678 rowsPerPageOptions: [{ type: Input }],
1679 alwaysShowPaginator: [{ type: Input }],
1680 paginatorPosition: [{ type: Input }],
1681 paginatorDropdownAppendTo: [{ type: Input }],
1682 paginatorDropdownScrollHeight: [{ type: Input }],
1683 currentPageReportTemplate: [{ type: Input }],
1684 showCurrentPageReport: [{ type: Input }],
1685 showJumpToPageDropdown: [{ type: Input }],
1686 showPageLinks: [{ type: Input }],
1687 defaultSortOrder: [{ type: Input }],
1688 sortMode: [{ type: Input }],
1689 resetPageOnSort: [{ type: Input }],
1690 selectionMode: [{ type: Input }],
1691 selectionChange: [{ type: Output }],
1692 contextMenuSelection: [{ type: Input }],
1693 contextMenuSelectionChange: [{ type: Output }],
1694 contextMenuSelectionMode: [{ type: Input }],
1695 dataKey: [{ type: Input }],
1696 metaKeySelection: [{ type: Input }],
1697 rowTrackBy: [{ type: Input }],
1698 lazy: [{ type: Input }],
1699 lazyLoadOnInit: [{ type: Input }],
1700 compareSelectionBy: [{ type: Input }],
1701 csvSeparator: [{ type: Input }],
1702 exportFilename: [{ type: Input }],
1703 filters: [{ type: Input }],
1704 globalFilterFields: [{ type: Input }],
1705 filterDelay: [{ type: Input }],
1706 filterLocale: [{ type: Input }],
1707 expandedRowKeys: [{ type: Input }],
1708 editingRowKeys: [{ type: Input }],
1709 rowExpandMode: [{ type: Input }],
1710 scrollable: [{ type: Input }],
1711 scrollHeight: [{ type: Input }],
1712 virtualScroll: [{ type: Input }],
1713 virtualScrollDelay: [{ type: Input }],
1714 virtualRowHeight: [{ type: Input }],
1715 frozenWidth: [{ type: Input }],
1716 responsive: [{ type: Input }],
1717 contextMenu: [{ type: Input }],
1718 resizableColumns: [{ type: Input }],
1719 columnResizeMode: [{ type: Input }],
1720 reorderableColumns: [{ type: Input }],
1721 loading: [{ type: Input }],
1722 loadingIcon: [{ type: Input }],
1723 showLoader: [{ type: Input }],
1724 rowHover: [{ type: Input }],
1725 customSort: [{ type: Input }],
1726 autoLayout: [{ type: Input }],
1727 exportFunction: [{ type: Input }],
1728 stateKey: [{ type: Input }],
1729 stateStorage: [{ type: Input }],
1730 editMode: [{ type: Input }],
1731 minBufferPx: [{ type: Input }],
1732 maxBufferPx: [{ type: Input }],
1733 onRowSelect: [{ type: Output }],
1734 onRowUnselect: [{ type: Output }],
1735 onPage: [{ type: Output }],
1736 onSort: [{ type: Output }],
1737 onFilter: [{ type: Output }],
1738 onLazyLoad: [{ type: Output }],
1739 onRowExpand: [{ type: Output }],
1740 onRowCollapse: [{ type: Output }],
1741 onContextMenuSelect: [{ type: Output }],
1742 onColResize: [{ type: Output }],
1743 onColReorder: [{ type: Output }],
1744 onRowReorder: [{ type: Output }],
1745 onEditInit: [{ type: Output }],
1746 onEditComplete: [{ type: Output }],
1747 onEditCancel: [{ type: Output }],
1748 onHeaderCheckboxToggle: [{ type: Output }],
1749 sortFunction: [{ type: Output }],
1750 firstChange: [{ type: Output }],
1751 rowsChange: [{ type: Output }],
1752 onStateSave: [{ type: Output }],
1753 onStateRestore: [{ type: Output }],
1754 containerViewChild: [{ type: ViewChild, args: ['container',] }],
1755 resizeHelperViewChild: [{ type: ViewChild, args: ['resizeHelper',] }],
1756 reorderIndicatorUpViewChild: [{ type: ViewChild, args: ['reorderIndicatorUp',] }],
1757 reorderIndicatorDownViewChild: [{ type: ViewChild, args: ['reorderIndicatorDown',] }],
1758 tableViewChild: [{ type: ViewChild, args: ['table',] }],
1759 scrollableViewChild: [{ type: ViewChild, args: ['scrollableView',] }],
1760 scrollableFrozenViewChild: [{ type: ViewChild, args: ['scrollableFrozenView',] }],
1761 templates: [{ type: ContentChildren, args: [PrimeTemplate,] }],
1762 value: [{ type: Input }],
1763 columns: [{ type: Input }],
1764 first: [{ type: Input }],
1765 rows: [{ type: Input }],
1766 totalRecords: [{ type: Input }],
1767 sortField: [{ type: Input }],
1768 sortOrder: [{ type: Input }],
1769 multiSortMeta: [{ type: Input }],
1770 selection: [{ type: Input }]
1771};
1772class TableBody {
1773 constructor(dt, tableService, cd) {
1774 this.dt = dt;
1775 this.tableService = tableService;
1776 this.cd = cd;
1777 this.subscription = this.dt.tableService.valueSource$.subscribe(() => {
1778 if (this.dt.virtualScroll) {
1779 this.cd.detectChanges();
1780 }
1781 });
1782 }
1783 ngOnDestroy() {
1784 if (this.subscription) {
1785 this.subscription.unsubscribe();
1786 }
1787 }
1788}
1789TableBody.decorators = [
1790 { type: Component, args: [{
1791 selector: '[pTableBody]',
1792 template: `
1793 <ng-container *ngIf="!dt.expandedRowTemplate && !dt.virtualScroll">
1794 <ng-template ngFor let-rowData let-rowIndex="index" [ngForOf]="(dt.paginator && !dt.lazy) ? ((dt.filteredValue||dt.value) | slice:dt.first:(dt.first + dt.rows)) : (dt.filteredValue||dt.value)" [ngForTrackBy]="dt.rowTrackBy">
1795 <ng-container *ngTemplateOutlet="template; context: {$implicit: rowData, rowIndex: dt.paginator ? (dt.first + rowIndex) : rowIndex, columns: columns, editing: (dt.editMode === 'row' && dt.isRowEditing(rowData))}"></ng-container>
1796 </ng-template>
1797 </ng-container>
1798 <ng-container *ngIf="!dt.expandedRowTemplate && dt.virtualScroll">
1799 <ng-template cdkVirtualFor let-rowData let-rowIndex="index" [cdkVirtualForOf]="dt.filteredValue||dt.value" [cdkVirtualForTrackBy]="dt.rowTrackBy" [cdkVirtualForTemplateCacheSize]="0">
1800 <ng-container *ngTemplateOutlet="rowData ? template: dt.loadingBodyTemplate; context: {$implicit: rowData, rowIndex: dt.paginator ? (dt.first + rowIndex) : rowIndex, columns: columns, editing: (dt.editMode === 'row' && dt.isRowEditing(rowData))}"></ng-container>
1801 </ng-template>
1802 </ng-container>
1803 <ng-container *ngIf="dt.expandedRowTemplate">
1804 <ng-template ngFor let-rowData let-rowIndex="index" [ngForOf]="(dt.paginator && !dt.lazy) ? ((dt.filteredValue||dt.value) | slice:dt.first:(dt.first + dt.rows)) : (dt.filteredValue||dt.value)" [ngForTrackBy]="dt.rowTrackBy">
1805 <ng-container *ngTemplateOutlet="template; context: {$implicit: rowData, rowIndex: dt.paginator ? (dt.first + rowIndex) : rowIndex, columns: columns, expanded: dt.isRowExpanded(rowData), editing: (dt.editMode === 'row' && dt.isRowEditing(rowData))}"></ng-container>
1806 <ng-container *ngIf="dt.isRowExpanded(rowData)">
1807 <ng-container *ngTemplateOutlet="dt.expandedRowTemplate; context: {$implicit: rowData, rowIndex: dt.paginator ? (dt.first + rowIndex) : rowIndex, columns: columns}"></ng-container>
1808 </ng-container>
1809 </ng-template>
1810 </ng-container>
1811 <ng-container *ngIf="dt.loading">
1812 <ng-container *ngTemplateOutlet="dt.loadingBodyTemplate; context: {$implicit: columns, frozen: frozen}"></ng-container>
1813 </ng-container>
1814 <ng-container *ngIf="dt.isEmpty() && !dt.loading">
1815 <ng-container *ngTemplateOutlet="dt.emptyMessageTemplate; context: {$implicit: columns, frozen: frozen}"></ng-container>
1816 </ng-container>
1817 `,
1818 changeDetection: ChangeDetectionStrategy.Default,
1819 encapsulation: ViewEncapsulation.None
1820 },] }
1821];
1822TableBody.ctorParameters = () => [
1823 { type: Table },
1824 { type: TableService },
1825 { type: ChangeDetectorRef }
1826];
1827TableBody.propDecorators = {
1828 columns: [{ type: Input, args: ["pTableBody",] }],
1829 template: [{ type: Input, args: ["pTableBodyTemplate",] }],
1830 frozen: [{ type: Input }]
1831};
1832class ScrollableView {
1833 constructor(dt, el, zone) {
1834 this.dt = dt;
1835 this.el = el;
1836 this.zone = zone;
1837 this.loadedPages = [];
1838 }
1839 get scrollHeight() {
1840 return this._scrollHeight;
1841 }
1842 set scrollHeight(val) {
1843 this._scrollHeight = val;
1844 if (val != null && (val.includes('%') || val.includes('calc'))) {
1845 console.log('Percentage scroll height calculation is removed in favor of the more performant CSS based flex mode, use scrollHeight="flex" instead.');
1846 }
1847 if (this.dt.virtualScroll && this.virtualScrollBody) {
1848 this.virtualScrollBody.checkViewportSize();
1849 }
1850 }
1851 ngAfterViewInit() {
1852 if (!this.frozen) {
1853 if (this.dt.frozenColumns || this.dt.frozenBodyTemplate) {
1854 DomHandler.addClass(this.el.nativeElement, 'p-datatable-unfrozen-view');
1855 }
1856 let frozenView = this.el.nativeElement.previousElementSibling;
1857 if (frozenView) {
1858 if (this.dt.virtualScroll)
1859 this.frozenSiblingBody = DomHandler.findSingle(frozenView, '.p-datatable-virtual-scrollable-body');
1860 else
1861 this.frozenSiblingBody = DomHandler.findSingle(frozenView, '.p-datatable-scrollable-body');
1862 }
1863 let scrollBarWidth = DomHandler.calculateScrollbarWidth();
1864 this.scrollHeaderBoxViewChild.nativeElement.style.paddingRight = scrollBarWidth + 'px';
1865 if (this.scrollFooterBoxViewChild && this.scrollFooterBoxViewChild.nativeElement) {
1866 this.scrollFooterBoxViewChild.nativeElement.style.paddingRight = scrollBarWidth + 'px';
1867 }
1868 }
1869 else {
1870 if (this.scrollableAlignerViewChild && this.scrollableAlignerViewChild.nativeElement) {
1871 this.scrollableAlignerViewChild.nativeElement.style.height = DomHandler.calculateScrollbarHeight() + 'px';
1872 }
1873 }
1874 this.bindEvents();
1875 }
1876 bindEvents() {
1877 this.zone.runOutsideAngular(() => {
1878 if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) {
1879 this.headerScrollListener = this.onHeaderScroll.bind(this);
1880 this.scrollHeaderViewChild.nativeElement.addEventListener('scroll', this.headerScrollListener);
1881 }
1882 if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) {
1883 this.footerScrollListener = this.onFooterScroll.bind(this);
1884 this.scrollFooterViewChild.nativeElement.addEventListener('scroll', this.footerScrollListener);
1885 }
1886 if (!this.frozen) {
1887 this.bodyScrollListener = this.onBodyScroll.bind(this);
1888 if (this.dt.virtualScroll)
1889 this.virtualScrollBody.getElementRef().nativeElement.addEventListener('scroll', this.bodyScrollListener);
1890 else
1891 this.scrollBodyViewChild.nativeElement.addEventListener('scroll', this.bodyScrollListener);
1892 }
1893 });
1894 }
1895 unbindEvents() {
1896 if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) {
1897 this.scrollHeaderViewChild.nativeElement.removeEventListener('scroll', this.headerScrollListener);
1898 }
1899 if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) {
1900 this.scrollFooterViewChild.nativeElement.removeEventListener('scroll', this.footerScrollListener);
1901 }
1902 if (this.scrollBodyViewChild && this.scrollBodyViewChild.nativeElement) {
1903 this.scrollBodyViewChild.nativeElement.removeEventListener('scroll', this.bodyScrollListener);
1904 }
1905 if (this.virtualScrollBody && this.virtualScrollBody.getElementRef()) {
1906 this.virtualScrollBody.getElementRef().nativeElement.removeEventListener('scroll', this.bodyScrollListener);
1907 }
1908 }
1909 onHeaderScroll() {
1910 const scrollLeft = this.scrollHeaderViewChild.nativeElement.scrollLeft;
1911 this.scrollBodyViewChild.nativeElement.scrollLeft = scrollLeft;
1912 if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) {
1913 this.scrollFooterViewChild.nativeElement.scrollLeft = scrollLeft;
1914 }
1915 this.preventBodyScrollPropagation = true;
1916 }
1917 onFooterScroll() {
1918 const scrollLeft = this.scrollFooterViewChild.nativeElement.scrollLeft;
1919 this.scrollBodyViewChild.nativeElement.scrollLeft = scrollLeft;
1920 if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) {
1921 this.scrollHeaderViewChild.nativeElement.scrollLeft = scrollLeft;
1922 }
1923 this.preventBodyScrollPropagation = true;
1924 }
1925 onBodyScroll(event) {
1926 if (this.preventBodyScrollPropagation) {
1927 this.preventBodyScrollPropagation = false;
1928 return;
1929 }
1930 if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) {
1931 this.scrollHeaderBoxViewChild.nativeElement.style.marginLeft = -1 * event.target.scrollLeft + 'px';
1932 }
1933 if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) {
1934 this.scrollFooterBoxViewChild.nativeElement.style.marginLeft = -1 * event.target.scrollLeft + 'px';
1935 }
1936 if (this.frozenSiblingBody) {
1937 this.frozenSiblingBody.scrollTop = event.target.scrollTop;
1938 }
1939 }
1940 onScrollIndexChange(index) {
1941 if (this.dt.lazy) {
1942 let pageRange = this.createPageRange(Math.floor(index / this.dt.rows));
1943 pageRange.forEach(page => this.loadPage(page));
1944 }
1945 }
1946 createPageRange(page) {
1947 let range = [];
1948 if (page !== 0) {
1949 range.push(page - 1);
1950 }
1951 range.push(page);
1952 if (page !== (this.getPageCount() - 1)) {
1953 range.push(page + 1);
1954 }
1955 return range;
1956 }
1957 loadPage(page) {
1958 if (!this.loadedPages.includes(page)) {
1959 this.dt.onLazyLoad.emit({
1960 first: this.dt.rows * page,
1961 rows: this.dt.rows,
1962 sortField: this.dt.sortField,
1963 sortOrder: this.dt.sortOrder,
1964 filters: this.dt.filters,
1965 globalFilter: this.dt.filters && this.dt.filters['global'] ? this.dt.filters['global'].value : null,
1966 multiSortMeta: this.dt.multiSortMeta
1967 });
1968 this.loadedPages.push(page);
1969 }
1970 }
1971 clearCache() {
1972 this.loadedPages = [];
1973 }
1974 getPageCount() {
1975 let dataToRender = this.dt.filteredValue || this.dt.value;
1976 let dataLength = dataToRender ? dataToRender.length : 0;
1977 return Math.ceil(dataLength / this.dt.rows);
1978 }
1979 scrollToVirtualIndex(index) {
1980 if (this.virtualScrollBody) {
1981 this.virtualScrollBody.scrollToIndex(index);
1982 }
1983 }
1984 scrollTo(options) {
1985 if (this.virtualScrollBody) {
1986 this.virtualScrollBody.scrollTo(options);
1987 }
1988 else {
1989 if (this.scrollBodyViewChild.nativeElement.scrollTo) {
1990 this.scrollBodyViewChild.nativeElement.scrollTo(options);
1991 }
1992 else {
1993 this.scrollBodyViewChild.nativeElement.scrollLeft = options.left;
1994 this.scrollBodyViewChild.nativeElement.scrollTop = options.top;
1995 }
1996 }
1997 }
1998 ngOnDestroy() {
1999 this.unbindEvents();
2000 this.frozenSiblingBody = null;
2001 }
2002}
2003ScrollableView.decorators = [
2004 { type: Component, args: [{
2005 selector: '[pScrollableView]',
2006 template: `
2007 <div #scrollHeader class="p-datatable-scrollable-header">
2008 <div #scrollHeaderBox class="p-datatable-scrollable-header-box">
2009 <table class="p-datatable-scrollable-header-table" [ngClass]="dt.tableStyleClass" [ngStyle]="dt.tableStyle">
2010 <ng-container *ngTemplateOutlet="frozen ? dt.frozenColGroupTemplate||dt.colGroupTemplate : dt.colGroupTemplate; context {$implicit: columns}"></ng-container>
2011 <thead class="p-datatable-thead">
2012 <ng-container *ngTemplateOutlet="frozen ? dt.frozenHeaderTemplate||dt.headerTemplate : dt.headerTemplate; context {$implicit: columns}"></ng-container>
2013 </thead>
2014 <tbody class="p-datatable-tbody">
2015 <ng-template ngFor let-rowData let-rowIndex="index" [ngForOf]="dt.frozenValue" [ngForTrackBy]="dt.rowTrackBy">
2016 <ng-container *ngTemplateOutlet="dt.frozenRowsTemplate; context: {$implicit: rowData, rowIndex: rowIndex, columns: columns}"></ng-container>
2017 </ng-template>
2018 </tbody>
2019 </table>
2020 </div>
2021 </div>
2022 <ng-container *ngIf="!dt.virtualScroll; else virtualScrollTemplate">
2023 <div #scrollBody class="p-datatable-scrollable-body" [ngStyle]="{'max-height': dt.scrollHeight !== 'flex' ? scrollHeight : undefined, 'overflow-y': !frozen && dt.scrollHeight ? 'scroll' : undefined}">
2024 <table #scrollTable [class]="dt.tableStyleClass" [ngStyle]="dt.tableStyle">
2025 <ng-container *ngTemplateOutlet="frozen ? dt.frozenColGroupTemplate||dt.colGroupTemplate : dt.colGroupTemplate; context {$implicit: columns}"></ng-container>
2026 <tbody class="p-datatable-tbody" [pTableBody]="columns" [pTableBodyTemplate]="frozen ? dt.frozenBodyTemplate||dt.bodyTemplate : dt.bodyTemplate" [frozen]="frozen"></tbody>
2027 </table>
2028 <div #scrollableAligner style="background-color:transparent" *ngIf="frozen"></div>
2029 </div>
2030 </ng-container>
2031 <ng-template #virtualScrollTemplate>
2032 <cdk-virtual-scroll-viewport [itemSize]="dt.virtualRowHeight" [style.height]="dt.scrollHeight !== 'flex' ? scrollHeight : undefined"
2033 [minBufferPx]="dt.minBufferPx" [maxBufferPx]="dt.maxBufferPx" (scrolledIndexChange)="onScrollIndexChange($event)" class="p-datatable-virtual-scrollable-body">
2034 <table #scrollTable [class]="dt.tableStyleClass" [ngStyle]="dt.tableStyle">
2035 <ng-container *ngTemplateOutlet="frozen ? dt.frozenColGroupTemplate||dt.colGroupTemplate : dt.colGroupTemplate; context {$implicit: columns}"></ng-container>
2036 <tbody class="p-datatable-tbody" [pTableBody]="columns" [pTableBodyTemplate]="frozen ? dt.frozenBodyTemplate||dt.bodyTemplate : dt.bodyTemplate" [frozen]="frozen"></tbody>
2037 </table>
2038 <div #scrollableAligner style="background-color:transparent" *ngIf="frozen"></div>
2039 </cdk-virtual-scroll-viewport>
2040 </ng-template>
2041 <div #scrollFooter class="p-datatable-scrollable-footer">
2042 <div #scrollFooterBox class="p-datatable-scrollable-footer-box">
2043 <table class="p-datatable-scrollable-footer-table" [ngClass]="dt.tableStyleClass" [ngStyle]="dt.tableStyle">
2044 <ng-container *ngTemplateOutlet="frozen ? dt.frozenColGroupTemplate||dt.colGroupTemplate : dt.colGroupTemplate; context {$implicit: columns}"></ng-container>
2045 <tfoot class="p-datatable-tfoot">
2046 <ng-container *ngTemplateOutlet="frozen ? dt.frozenFooterTemplate||dt.footerTemplate : dt.footerTemplate; context {$implicit: columns}"></ng-container>
2047 </tfoot>
2048 </table>
2049 </div>
2050 </div>
2051 `,
2052 changeDetection: ChangeDetectionStrategy.Default,
2053 encapsulation: ViewEncapsulation.None
2054 },] }
2055];
2056ScrollableView.ctorParameters = () => [
2057 { type: Table },
2058 { type: ElementRef },
2059 { type: NgZone }
2060];
2061ScrollableView.propDecorators = {
2062 columns: [{ type: Input, args: ["pScrollableView",] }],
2063 frozen: [{ type: Input }],
2064 scrollHeaderViewChild: [{ type: ViewChild, args: ['scrollHeader',] }],
2065 scrollHeaderBoxViewChild: [{ type: ViewChild, args: ['scrollHeaderBox',] }],
2066 scrollBodyViewChild: [{ type: ViewChild, args: ['scrollBody',] }],
2067 scrollTableViewChild: [{ type: ViewChild, args: ['scrollTable',] }],
2068 scrollFooterViewChild: [{ type: ViewChild, args: ['scrollFooter',] }],
2069 scrollFooterBoxViewChild: [{ type: ViewChild, args: ['scrollFooterBox',] }],
2070 scrollableAlignerViewChild: [{ type: ViewChild, args: ['scrollableAligner',] }],
2071 virtualScrollBody: [{ type: ViewChild, args: [CdkVirtualScrollViewport,] }],
2072 scrollHeight: [{ type: Input }]
2073};
2074class SortableColumn {
2075 constructor(dt) {
2076 this.dt = dt;
2077 if (this.isEnabled()) {
2078 this.subscription = this.dt.tableService.sortSource$.subscribe(sortMeta => {
2079 this.updateSortState();
2080 });
2081 }
2082 }
2083 ngOnInit() {
2084 if (this.isEnabled()) {
2085 this.updateSortState();
2086 }
2087 }
2088 updateSortState() {
2089 this.sorted = this.dt.isSorted(this.field);
2090 this.sortOrder = this.sorted ? (this.dt.sortOrder === 1 ? 'ascending' : 'descending') : 'none';
2091 }
2092 onClick(event) {
2093 if (this.isEnabled()) {
2094 this.updateSortState();
2095 this.dt.sort({
2096 originalEvent: event,
2097 field: this.field
2098 });
2099 DomHandler.clearSelection();
2100 }
2101 }
2102 onEnterKey(event) {
2103 this.onClick(event);
2104 }
2105 isEnabled() {
2106 return this.pSortableColumnDisabled !== true;
2107 }
2108 ngOnDestroy() {
2109 if (this.subscription) {
2110 this.subscription.unsubscribe();
2111 }
2112 }
2113}
2114SortableColumn.decorators = [
2115 { type: Directive, args: [{
2116 selector: '[pSortableColumn]',
2117 host: {
2118 '[class.p-sortable-column]': 'isEnabled()',
2119 '[class.p-highlight]': 'sorted',
2120 '[attr.tabindex]': 'isEnabled() ? "0" : null',
2121 '[attr.role]': '"columnheader"',
2122 '[attr.aria-sort]': 'sortOrder'
2123 }
2124 },] }
2125];
2126SortableColumn.ctorParameters = () => [
2127 { type: Table }
2128];
2129SortableColumn.propDecorators = {
2130 field: [{ type: Input, args: ["pSortableColumn",] }],
2131 pSortableColumnDisabled: [{ type: Input }],
2132 onClick: [{ type: HostListener, args: ['click', ['$event'],] }],
2133 onEnterKey: [{ type: HostListener, args: ['keydown.enter', ['$event'],] }]
2134};
2135class SortIcon {
2136 constructor(dt, cd) {
2137 this.dt = dt;
2138 this.cd = cd;
2139 this.subscription = this.dt.tableService.sortSource$.subscribe(sortMeta => {
2140 this.updateSortState();
2141 });
2142 }
2143 ngOnInit() {
2144 this.updateSortState();
2145 }
2146 onClick(event) {
2147 event.preventDefault();
2148 }
2149 updateSortState() {
2150 if (this.dt.sortMode === 'single') {
2151 this.sortOrder = this.dt.isSorted(this.field) ? this.dt.sortOrder : 0;
2152 }
2153 else if (this.dt.sortMode === 'multiple') {
2154 let sortMeta = this.dt.getSortMeta(this.field);
2155 this.sortOrder = sortMeta ? sortMeta.order : 0;
2156 }
2157 this.cd.markForCheck();
2158 }
2159 ngOnDestroy() {
2160 if (this.subscription) {
2161 this.subscription.unsubscribe();
2162 }
2163 }
2164}
2165SortIcon.decorators = [
2166 { type: Component, args: [{
2167 selector: 'p-sortIcon',
2168 template: `
2169 <i class="p-sortable-column-icon pi pi-fw" [ngClass]="{'pi-sort-amount-up-alt': sortOrder === 1, 'pi-sort-amount-down': sortOrder === -1, 'pi-sort-alt': sortOrder === 0}"></i>
2170 `,
2171 changeDetection: ChangeDetectionStrategy.OnPush,
2172 encapsulation: ViewEncapsulation.None
2173 },] }
2174];
2175SortIcon.ctorParameters = () => [
2176 { type: Table },
2177 { type: ChangeDetectorRef }
2178];
2179SortIcon.propDecorators = {
2180 field: [{ type: Input }]
2181};
2182class SelectableRow {
2183 constructor(dt, tableService) {
2184 this.dt = dt;
2185 this.tableService = tableService;
2186 if (this.isEnabled()) {
2187 this.subscription = this.dt.tableService.selectionSource$.subscribe(() => {
2188 this.selected = this.dt.isSelected(this.data);
2189 });
2190 }
2191 }
2192 ngOnInit() {
2193 if (this.isEnabled()) {
2194 this.selected = this.dt.isSelected(this.data);
2195 }
2196 }
2197 onClick(event) {
2198 if (this.isEnabled()) {
2199 this.dt.handleRowClick({
2200 originalEvent: event,
2201 rowData: this.data,
2202 rowIndex: this.index
2203 });
2204 }
2205 }
2206 onTouchEnd(event) {
2207 if (this.isEnabled()) {
2208 this.dt.handleRowTouchEnd(event);
2209 }
2210 }
2211 onArrowDownKeyDown(event) {
2212 if (!this.isEnabled()) {
2213 return;
2214 }
2215 const row = event.currentTarget;
2216 const nextRow = this.findNextSelectableRow(row);
2217 if (nextRow) {
2218 nextRow.focus();
2219 }
2220 event.preventDefault();
2221 }
2222 onArrowUpKeyDown(event) {
2223 if (!this.isEnabled()) {
2224 return;
2225 }
2226 const row = event.currentTarget;
2227 const prevRow = this.findPrevSelectableRow(row);
2228 if (prevRow) {
2229 prevRow.focus();
2230 }
2231 event.preventDefault();
2232 }
2233 onEnterKeyDown(event) {
2234 if (!this.isEnabled()) {
2235 return;
2236 }
2237 this.dt.handleRowClick({
2238 originalEvent: event,
2239 rowData: this.data,
2240 rowIndex: this.index
2241 });
2242 }
2243 findNextSelectableRow(row) {
2244 let nextRow = row.nextElementSibling;
2245 if (nextRow) {
2246 if (DomHandler.hasClass(nextRow, 'p-datatable-selectable-row'))
2247 return nextRow;
2248 else
2249 return this.findNextSelectableRow(nextRow);
2250 }
2251 else {
2252 return null;
2253 }
2254 }
2255 findPrevSelectableRow(row) {
2256 let prevRow = row.previousElementSibling;
2257 if (prevRow) {
2258 if (DomHandler.hasClass(prevRow, 'p-datatable-selectable-row'))
2259 return prevRow;
2260 else
2261 return this.findPrevSelectableRow(prevRow);
2262 }
2263 else {
2264 return null;
2265 }
2266 }
2267 isEnabled() {
2268 return this.pSelectableRowDisabled !== true;
2269 }
2270 ngOnDestroy() {
2271 if (this.subscription) {
2272 this.subscription.unsubscribe();
2273 }
2274 }
2275}
2276SelectableRow.decorators = [
2277 { type: Directive, args: [{
2278 selector: '[pSelectableRow]',
2279 host: {
2280 '[class.p-selectable-row]': 'isEnabled()',
2281 '[class.p-highlight]': 'selected',
2282 '[attr.tabindex]': 'isEnabled() ? 0 : undefined'
2283 }
2284 },] }
2285];
2286SelectableRow.ctorParameters = () => [
2287 { type: Table },
2288 { type: TableService }
2289];
2290SelectableRow.propDecorators = {
2291 data: [{ type: Input, args: ["pSelectableRow",] }],
2292 index: [{ type: Input, args: ["pSelectableRowIndex",] }],
2293 pSelectableRowDisabled: [{ type: Input }],
2294 onClick: [{ type: HostListener, args: ['click', ['$event'],] }],
2295 onTouchEnd: [{ type: HostListener, args: ['touchend', ['$event'],] }],
2296 onArrowDownKeyDown: [{ type: HostListener, args: ['keydown.arrowdown', ['$event'],] }],
2297 onArrowUpKeyDown: [{ type: HostListener, args: ['keydown.arrowup', ['$event'],] }],
2298 onEnterKeyDown: [{ type: HostListener, args: ['keydown.enter', ['$event'],] }]
2299};
2300class SelectableRowDblClick {
2301 constructor(dt, tableService) {
2302 this.dt = dt;
2303 this.tableService = tableService;
2304 if (this.isEnabled()) {
2305 this.subscription = this.dt.tableService.selectionSource$.subscribe(() => {
2306 this.selected = this.dt.isSelected(this.data);
2307 });
2308 }
2309 }
2310 ngOnInit() {
2311 if (this.isEnabled()) {
2312 this.selected = this.dt.isSelected(this.data);
2313 }
2314 }
2315 onClick(event) {
2316 if (this.isEnabled()) {
2317 this.dt.handleRowClick({
2318 originalEvent: event,
2319 rowData: this.data,
2320 rowIndex: this.index
2321 });
2322 }
2323 }
2324 isEnabled() {
2325 return this.pSelectableRowDisabled !== true;
2326 }
2327 ngOnDestroy() {
2328 if (this.subscription) {
2329 this.subscription.unsubscribe();
2330 }
2331 }
2332}
2333SelectableRowDblClick.decorators = [
2334 { type: Directive, args: [{
2335 selector: '[pSelectableRowDblClick]',
2336 host: {
2337 '[class.p-datatable-selectable-row]': 'isEnabled()',
2338 '[class.p-highlight]': 'selected'
2339 }
2340 },] }
2341];
2342SelectableRowDblClick.ctorParameters = () => [
2343 { type: Table },
2344 { type: TableService }
2345];
2346SelectableRowDblClick.propDecorators = {
2347 data: [{ type: Input, args: ["pSelectableRowDblClick",] }],
2348 index: [{ type: Input, args: ["pSelectableRowIndex",] }],
2349 pSelectableRowDisabled: [{ type: Input }],
2350 onClick: [{ type: HostListener, args: ['dblclick', ['$event'],] }]
2351};
2352class ContextMenuRow {
2353 constructor(dt, tableService, el) {
2354 this.dt = dt;
2355 this.tableService = tableService;
2356 this.el = el;
2357 if (this.isEnabled()) {
2358 this.subscription = this.dt.tableService.contextMenuSource$.subscribe((data) => {
2359 this.selected = this.dt.equals(this.data, data);
2360 });
2361 }
2362 }
2363 onContextMenu(event) {
2364 if (this.isEnabled()) {
2365 this.dt.handleRowRightClick({
2366 originalEvent: event,
2367 rowData: this.data,
2368 rowIndex: this.index
2369 });
2370 this.el.nativeElement.focus();
2371 event.preventDefault();
2372 }
2373 }
2374 isEnabled() {
2375 return this.pContextMenuRowDisabled !== true;
2376 }
2377 ngOnDestroy() {
2378 if (this.subscription) {
2379 this.subscription.unsubscribe();
2380 }
2381 }
2382}
2383ContextMenuRow.decorators = [
2384 { type: Directive, args: [{
2385 selector: '[pContextMenuRow]',
2386 host: {
2387 '[class.p-highlight-contextmenu]': 'selected',
2388 '[attr.tabindex]': 'isEnabled() ? 0 : undefined'
2389 }
2390 },] }
2391];
2392ContextMenuRow.ctorParameters = () => [
2393 { type: Table },
2394 { type: TableService },
2395 { type: ElementRef }
2396];
2397ContextMenuRow.propDecorators = {
2398 data: [{ type: Input, args: ["pContextMenuRow",] }],
2399 index: [{ type: Input, args: ["pContextMenuRowIndex",] }],
2400 pContextMenuRowDisabled: [{ type: Input }],
2401 onContextMenu: [{ type: HostListener, args: ['contextmenu', ['$event'],] }]
2402};
2403class RowToggler {
2404 constructor(dt) {
2405 this.dt = dt;
2406 }
2407 onClick(event) {
2408 if (this.isEnabled()) {
2409 this.dt.toggleRow(this.data, event);
2410 event.preventDefault();
2411 }
2412 }
2413 isEnabled() {
2414 return this.pRowTogglerDisabled !== true;
2415 }
2416}
2417RowToggler.decorators = [
2418 { type: Directive, args: [{
2419 selector: '[pRowToggler]'
2420 },] }
2421];
2422RowToggler.ctorParameters = () => [
2423 { type: Table }
2424];
2425RowToggler.propDecorators = {
2426 data: [{ type: Input, args: ['pRowToggler',] }],
2427 pRowTogglerDisabled: [{ type: Input }],
2428 onClick: [{ type: HostListener, args: ['click', ['$event'],] }]
2429};
2430class ResizableColumn {
2431 constructor(dt, el, zone) {
2432 this.dt = dt;
2433 this.el = el;
2434 this.zone = zone;
2435 }
2436 ngAfterViewInit() {
2437 if (this.isEnabled()) {
2438 DomHandler.addClass(this.el.nativeElement, 'p-resizable-column');
2439 this.resizer = document.createElement('span');
2440 this.resizer.className = 'p-column-resizer';
2441 this.el.nativeElement.appendChild(this.resizer);
2442 this.zone.runOutsideAngular(() => {
2443 this.resizerMouseDownListener = this.onMouseDown.bind(this);
2444 this.resizer.addEventListener('mousedown', this.resizerMouseDownListener);
2445 });
2446 }
2447 }
2448 bindDocumentEvents() {
2449 this.zone.runOutsideAngular(() => {
2450 this.documentMouseMoveListener = this.onDocumentMouseMove.bind(this);
2451 document.addEventListener('mousemove', this.documentMouseMoveListener);
2452 this.documentMouseUpListener = this.onDocumentMouseUp.bind(this);
2453 document.addEventListener('mouseup', this.documentMouseUpListener);
2454 });
2455 }
2456 unbindDocumentEvents() {
2457 if (this.documentMouseMoveListener) {
2458 document.removeEventListener('mousemove', this.documentMouseMoveListener);
2459 this.documentMouseMoveListener = null;
2460 }
2461 if (this.documentMouseUpListener) {
2462 document.removeEventListener('mouseup', this.documentMouseUpListener);
2463 this.documentMouseUpListener = null;
2464 }
2465 }
2466 onMouseDown(event) {
2467 if (event.which === 1) {
2468 this.dt.onColumnResizeBegin(event);
2469 this.bindDocumentEvents();
2470 }
2471 }
2472 onDocumentMouseMove(event) {
2473 this.dt.onColumnResize(event);
2474 }
2475 onDocumentMouseUp(event) {
2476 this.dt.onColumnResizeEnd(event, this.el.nativeElement);
2477 this.unbindDocumentEvents();
2478 }
2479 isEnabled() {
2480 return this.pResizableColumnDisabled !== true;
2481 }
2482 ngOnDestroy() {
2483 if (this.resizerMouseDownListener) {
2484 this.resizer.removeEventListener('mousedown', this.resizerMouseDownListener);
2485 }
2486 this.unbindDocumentEvents();
2487 }
2488}
2489ResizableColumn.decorators = [
2490 { type: Directive, args: [{
2491 selector: '[pResizableColumn]'
2492 },] }
2493];
2494ResizableColumn.ctorParameters = () => [
2495 { type: Table },
2496 { type: ElementRef },
2497 { type: NgZone }
2498];
2499ResizableColumn.propDecorators = {
2500 pResizableColumnDisabled: [{ type: Input }]
2501};
2502class ReorderableColumn {
2503 constructor(dt, el, zone) {
2504 this.dt = dt;
2505 this.el = el;
2506 this.zone = zone;
2507 }
2508 ngAfterViewInit() {
2509 if (this.isEnabled()) {
2510 this.bindEvents();
2511 }
2512 }
2513 bindEvents() {
2514 this.zone.runOutsideAngular(() => {
2515 this.mouseDownListener = this.onMouseDown.bind(this);
2516 this.el.nativeElement.addEventListener('mousedown', this.mouseDownListener);
2517 this.dragStartListener = this.onDragStart.bind(this);
2518 this.el.nativeElement.addEventListener('dragstart', this.dragStartListener);
2519 this.dragOverListener = this.onDragEnter.bind(this);
2520 this.el.nativeElement.addEventListener('dragover', this.dragOverListener);
2521 this.dragEnterListener = this.onDragEnter.bind(this);
2522 this.el.nativeElement.addEventListener('dragenter', this.dragEnterListener);
2523 this.dragLeaveListener = this.onDragLeave.bind(this);
2524 this.el.nativeElement.addEventListener('dragleave', this.dragLeaveListener);
2525 });
2526 }
2527 unbindEvents() {
2528 if (this.mouseDownListener) {
2529 document.removeEventListener('mousedown', this.mouseDownListener);
2530 this.mouseDownListener = null;
2531 }
2532 if (this.dragOverListener) {
2533 document.removeEventListener('dragover', this.dragOverListener);
2534 this.dragOverListener = null;
2535 }
2536 if (this.dragEnterListener) {
2537 document.removeEventListener('dragenter', this.dragEnterListener);
2538 this.dragEnterListener = null;
2539 }
2540 if (this.dragEnterListener) {
2541 document.removeEventListener('dragenter', this.dragEnterListener);
2542 this.dragEnterListener = null;
2543 }
2544 if (this.dragLeaveListener) {
2545 document.removeEventListener('dragleave', this.dragLeaveListener);
2546 this.dragLeaveListener = null;
2547 }
2548 }
2549 onMouseDown(event) {
2550 if (event.target.nodeName === 'INPUT' || event.target.nodeName === 'TEXTAREA' || DomHandler.hasClass(event.target, 'p-column-resizer'))
2551 this.el.nativeElement.draggable = false;
2552 else
2553 this.el.nativeElement.draggable = true;
2554 }
2555 onDragStart(event) {
2556 this.dt.onColumnDragStart(event, this.el.nativeElement);
2557 }
2558 onDragOver(event) {
2559 event.preventDefault();
2560 }
2561 onDragEnter(event) {
2562 this.dt.onColumnDragEnter(event, this.el.nativeElement);
2563 }
2564 onDragLeave(event) {
2565 this.dt.onColumnDragLeave(event);
2566 }
2567 onDrop(event) {
2568 if (this.isEnabled()) {
2569 this.dt.onColumnDrop(event, this.el.nativeElement);
2570 }
2571 }
2572 isEnabled() {
2573 return this.pReorderableColumnDisabled !== true;
2574 }
2575 ngOnDestroy() {
2576 this.unbindEvents();
2577 }
2578}
2579ReorderableColumn.decorators = [
2580 { type: Directive, args: [{
2581 selector: '[pReorderableColumn]'
2582 },] }
2583];
2584ReorderableColumn.ctorParameters = () => [
2585 { type: Table },
2586 { type: ElementRef },
2587 { type: NgZone }
2588];
2589ReorderableColumn.propDecorators = {
2590 pReorderableColumnDisabled: [{ type: Input }],
2591 onDrop: [{ type: HostListener, args: ['drop', ['$event'],] }]
2592};
2593class EditableColumn {
2594 constructor(dt, el, zone) {
2595 this.dt = dt;
2596 this.el = el;
2597 this.zone = zone;
2598 }
2599 ngAfterViewInit() {
2600 if (this.isEnabled()) {
2601 DomHandler.addClass(this.el.nativeElement, 'p-editable-column');
2602 }
2603 }
2604 onClick(event) {
2605 if (this.isEnabled()) {
2606 this.dt.editingCellClick = true;
2607 if (this.dt.editingCell) {
2608 if (this.dt.editingCell !== this.el.nativeElement) {
2609 if (!this.dt.isEditingCellValid()) {
2610 return;
2611 }
2612 this.closeEditingCell(true, event);
2613 this.openCell();
2614 }
2615 }
2616 else {
2617 this.openCell();
2618 }
2619 }
2620 }
2621 openCell() {
2622 this.dt.updateEditingCell(this.el.nativeElement, this.data, this.field, this.rowIndex);
2623 DomHandler.addClass(this.el.nativeElement, 'p-cell-editing');
2624 this.dt.onEditInit.emit({ field: this.field, data: this.data, index: this.rowIndex });
2625 this.zone.runOutsideAngular(() => {
2626 setTimeout(() => {
2627 let focusCellSelector = this.pFocusCellSelector || 'input, textarea, select';
2628 let focusableElement = DomHandler.findSingle(this.el.nativeElement, focusCellSelector);
2629 if (focusableElement) {
2630 focusableElement.focus();
2631 }
2632 }, 50);
2633 });
2634 }
2635 closeEditingCell(completed, event) {
2636 if (completed)
2637 this.dt.onEditComplete.emit({ field: this.dt.editingCellField, data: this.dt.editingCellData, originalEvent: event, index: this.rowIndex });
2638 else
2639 this.dt.onEditCancel.emit({ field: this.dt.editingCellField, data: this.dt.editingCellData, originalEvent: event, index: this.rowIndex });
2640 DomHandler.removeClass(this.dt.editingCell, 'p-cell-editing');
2641 this.dt.editingCell = null;
2642 this.dt.editingCellData = null;
2643 this.dt.editingCellField = null;
2644 this.dt.unbindDocumentEditListener();
2645 }
2646 onEnterKeyDown(event) {
2647 if (this.isEnabled()) {
2648 if (this.dt.isEditingCellValid()) {
2649 this.closeEditingCell(true, event);
2650 }
2651 event.preventDefault();
2652 }
2653 }
2654 onEscapeKeyDown(event) {
2655 if (this.isEnabled()) {
2656 if (this.dt.isEditingCellValid()) {
2657 this.closeEditingCell(false, event);
2658 }
2659 event.preventDefault();
2660 }
2661 }
2662 onShiftKeyDown(event) {
2663 if (this.isEnabled()) {
2664 if (event.shiftKey)
2665 this.moveToPreviousCell(event);
2666 else {
2667 this.moveToNextCell(event);
2668 }
2669 }
2670 }
2671 findCell(element) {
2672 if (element) {
2673 let cell = element;
2674 while (cell && !DomHandler.hasClass(cell, 'p-cell-editing')) {
2675 cell = cell.parentElement;
2676 }
2677 return cell;
2678 }
2679 else {
2680 return null;
2681 }
2682 }
2683 moveToPreviousCell(event) {
2684 let currentCell = this.findCell(event.target);
2685 if (currentCell) {
2686 let targetCell = this.findPreviousEditableColumn(currentCell);
2687 if (targetCell) {
2688 if (this.dt.isEditingCellValid()) {
2689 this.closeEditingCell(true, event);
2690 }
2691 DomHandler.invokeElementMethod(event.target, 'blur');
2692 DomHandler.invokeElementMethod(targetCell, 'click');
2693 event.preventDefault();
2694 }
2695 }
2696 }
2697 moveToNextCell(event) {
2698 let currentCell = this.findCell(event.target);
2699 if (currentCell) {
2700 let targetCell = this.findNextEditableColumn(currentCell);
2701 if (targetCell) {
2702 if (this.dt.isEditingCellValid()) {
2703 this.closeEditingCell(true, event);
2704 }
2705 DomHandler.invokeElementMethod(event.target, 'blur');
2706 DomHandler.invokeElementMethod(targetCell, 'click');
2707 event.preventDefault();
2708 }
2709 }
2710 }
2711 findPreviousEditableColumn(cell) {
2712 let prevCell = cell.previousElementSibling;
2713 if (!prevCell) {
2714 let previousRow = cell.parentElement.previousElementSibling;
2715 if (previousRow) {
2716 prevCell = previousRow.lastElementChild;
2717 }
2718 }
2719 if (prevCell) {
2720 if (DomHandler.hasClass(prevCell, 'p-editable-column'))
2721 return prevCell;
2722 else
2723 return this.findPreviousEditableColumn(prevCell);
2724 }
2725 else {
2726 return null;
2727 }
2728 }
2729 findNextEditableColumn(cell) {
2730 let nextCell = cell.nextElementSibling;
2731 if (!nextCell) {
2732 let nextRow = cell.parentElement.nextElementSibling;
2733 if (nextRow) {
2734 nextCell = nextRow.firstElementChild;
2735 }
2736 }
2737 if (nextCell) {
2738 if (DomHandler.hasClass(nextCell, 'p-editable-column'))
2739 return nextCell;
2740 else
2741 return this.findNextEditableColumn(nextCell);
2742 }
2743 else {
2744 return null;
2745 }
2746 }
2747 isEnabled() {
2748 return this.pEditableColumnDisabled !== true;
2749 }
2750}
2751EditableColumn.decorators = [
2752 { type: Directive, args: [{
2753 selector: '[pEditableColumn]'
2754 },] }
2755];
2756EditableColumn.ctorParameters = () => [
2757 { type: Table },
2758 { type: ElementRef },
2759 { type: NgZone }
2760];
2761EditableColumn.propDecorators = {
2762 data: [{ type: Input, args: ["pEditableColumn",] }],
2763 field: [{ type: Input, args: ["pEditableColumnField",] }],
2764 rowIndex: [{ type: Input, args: ["pEditableColumnRowIndex",] }],
2765 pEditableColumnDisabled: [{ type: Input }],
2766 pFocusCellSelector: [{ type: Input }],
2767 onClick: [{ type: HostListener, args: ['click', ['$event'],] }],
2768 onEnterKeyDown: [{ type: HostListener, args: ['keydown.enter', ['$event'],] }],
2769 onEscapeKeyDown: [{ type: HostListener, args: ['keydown.escape', ['$event'],] }],
2770 onShiftKeyDown: [{ type: HostListener, args: ['keydown.tab', ['$event'],] }, { type: HostListener, args: ['keydown.shift.tab', ['$event'],] }, { type: HostListener, args: ['keydown.meta.tab', ['$event'],] }]
2771};
2772class EditableRow {
2773 constructor(el) {
2774 this.el = el;
2775 }
2776 isEnabled() {
2777 return this.pEditableRowDisabled !== true;
2778 }
2779}
2780EditableRow.decorators = [
2781 { type: Directive, args: [{
2782 selector: '[pEditableRow]'
2783 },] }
2784];
2785EditableRow.ctorParameters = () => [
2786 { type: ElementRef }
2787];
2788EditableRow.propDecorators = {
2789 data: [{ type: Input, args: ["pEditableRow",] }],
2790 pEditableRowDisabled: [{ type: Input }]
2791};
2792class InitEditableRow {
2793 constructor(dt, editableRow) {
2794 this.dt = dt;
2795 this.editableRow = editableRow;
2796 }
2797 onClick(event) {
2798 this.dt.initRowEdit(this.editableRow.data);
2799 event.preventDefault();
2800 }
2801}
2802InitEditableRow.decorators = [
2803 { type: Directive, args: [{
2804 selector: '[pInitEditableRow]'
2805 },] }
2806];
2807InitEditableRow.ctorParameters = () => [
2808 { type: Table },
2809 { type: EditableRow }
2810];
2811InitEditableRow.propDecorators = {
2812 onClick: [{ type: HostListener, args: ['click', ['$event'],] }]
2813};
2814class SaveEditableRow {
2815 constructor(dt, editableRow) {
2816 this.dt = dt;
2817 this.editableRow = editableRow;
2818 }
2819 onClick(event) {
2820 this.dt.saveRowEdit(this.editableRow.data, this.editableRow.el.nativeElement);
2821 event.preventDefault();
2822 }
2823}
2824SaveEditableRow.decorators = [
2825 { type: Directive, args: [{
2826 selector: '[pSaveEditableRow]'
2827 },] }
2828];
2829SaveEditableRow.ctorParameters = () => [
2830 { type: Table },
2831 { type: EditableRow }
2832];
2833SaveEditableRow.propDecorators = {
2834 onClick: [{ type: HostListener, args: ['click', ['$event'],] }]
2835};
2836class CancelEditableRow {
2837 constructor(dt, editableRow) {
2838 this.dt = dt;
2839 this.editableRow = editableRow;
2840 }
2841 onClick(event) {
2842 this.dt.cancelRowEdit(this.editableRow.data);
2843 event.preventDefault();
2844 }
2845}
2846CancelEditableRow.decorators = [
2847 { type: Directive, args: [{
2848 selector: '[pCancelEditableRow]'
2849 },] }
2850];
2851CancelEditableRow.ctorParameters = () => [
2852 { type: Table },
2853 { type: EditableRow }
2854];
2855CancelEditableRow.propDecorators = {
2856 onClick: [{ type: HostListener, args: ['click', ['$event'],] }]
2857};
2858class CellEditor {
2859 constructor(dt, editableColumn, editableRow) {
2860 this.dt = dt;
2861 this.editableColumn = editableColumn;
2862 this.editableRow = editableRow;
2863 }
2864 ngAfterContentInit() {
2865 this.templates.forEach((item) => {
2866 switch (item.getType()) {
2867 case 'input':
2868 this.inputTemplate = item.template;
2869 break;
2870 case 'output':
2871 this.outputTemplate = item.template;
2872 break;
2873 }
2874 });
2875 }
2876 get editing() {
2877 return (this.dt.editingCell && this.editableColumn && this.dt.editingCell === this.editableColumn.el.nativeElement) ||
2878 (this.editableRow && this.dt.editMode === 'row' && this.dt.isRowEditing(this.editableRow.data));
2879 }
2880}
2881CellEditor.decorators = [
2882 { type: Component, args: [{
2883 selector: 'p-cellEditor',
2884 template: `
2885 <ng-container *ngIf="editing">
2886 <ng-container *ngTemplateOutlet="inputTemplate"></ng-container>
2887 </ng-container>
2888 <ng-container *ngIf="!editing">
2889 <ng-container *ngTemplateOutlet="outputTemplate"></ng-container>
2890 </ng-container>
2891 `,
2892 encapsulation: ViewEncapsulation.None
2893 },] }
2894];
2895CellEditor.ctorParameters = () => [
2896 { type: Table },
2897 { type: EditableColumn, decorators: [{ type: Optional }] },
2898 { type: EditableRow, decorators: [{ type: Optional }] }
2899];
2900CellEditor.propDecorators = {
2901 templates: [{ type: ContentChildren, args: [PrimeTemplate,] }]
2902};
2903class TableRadioButton {
2904 constructor(dt, tableService, cd) {
2905 this.dt = dt;
2906 this.tableService = tableService;
2907 this.cd = cd;
2908 this.subscription = this.dt.tableService.selectionSource$.subscribe(() => {
2909 this.checked = this.dt.isSelected(this.value);
2910 this.cd.markForCheck();
2911 });
2912 }
2913 ngOnInit() {
2914 this.checked = this.dt.isSelected(this.value);
2915 }
2916 onClick(event) {
2917 if (!this.disabled) {
2918 this.dt.toggleRowWithRadio({
2919 originalEvent: event,
2920 rowIndex: this.index
2921 }, this.value);
2922 }
2923 DomHandler.clearSelection();
2924 }
2925 onFocus() {
2926 DomHandler.addClass(this.boxViewChild.nativeElement, 'p-focus');
2927 }
2928 onBlur() {
2929 DomHandler.removeClass(this.boxViewChild.nativeElement, 'p-focus');
2930 }
2931 ngOnDestroy() {
2932 if (this.subscription) {
2933 this.subscription.unsubscribe();
2934 }
2935 }
2936}
2937TableRadioButton.decorators = [
2938 { type: Component, args: [{
2939 selector: 'p-tableRadioButton',
2940 template: `
2941 <div class="p-radiobutton p-component" (click)="onClick($event)">
2942 <div class="p-hidden-accessible">
2943 <input type="radio" [attr.id]="inputId" [attr.name]="name" [checked]="checked" (focus)="onFocus()" (blur)="onBlur()"
2944 [disabled]="disabled" [attr.aria-label]="ariaLabel">
2945 </div>
2946 <div #box [ngClass]="{'p-radiobutton-box p-component':true,
2947 'p-highlight':checked, 'p-disabled':disabled}" role="radio" [attr.aria-checked]="checked">
2948 <div class="p-radiobutton-icon"></div>
2949 </div>
2950 </div>
2951 `,
2952 changeDetection: ChangeDetectionStrategy.OnPush,
2953 encapsulation: ViewEncapsulation.None
2954 },] }
2955];
2956TableRadioButton.ctorParameters = () => [
2957 { type: Table },
2958 { type: TableService },
2959 { type: ChangeDetectorRef }
2960];
2961TableRadioButton.propDecorators = {
2962 disabled: [{ type: Input }],
2963 value: [{ type: Input }],
2964 index: [{ type: Input }],
2965 inputId: [{ type: Input }],
2966 name: [{ type: Input }],
2967 ariaLabel: [{ type: Input }],
2968 boxViewChild: [{ type: ViewChild, args: ['box',] }]
2969};
2970class TableCheckbox {
2971 constructor(dt, tableService, cd) {
2972 this.dt = dt;
2973 this.tableService = tableService;
2974 this.cd = cd;
2975 this.subscription = this.dt.tableService.selectionSource$.subscribe(() => {
2976 this.checked = this.dt.isSelected(this.value);
2977 this.cd.markForCheck();
2978 });
2979 }
2980 ngOnInit() {
2981 this.checked = this.dt.isSelected(this.value);
2982 }
2983 onClick(event) {
2984 if (!this.disabled) {
2985 this.dt.toggleRowWithCheckbox({
2986 originalEvent: event,
2987 rowIndex: this.index
2988 }, this.value);
2989 }
2990 DomHandler.clearSelection();
2991 }
2992 onFocus() {
2993 DomHandler.addClass(this.boxViewChild.nativeElement, 'p-focus');
2994 }
2995 onBlur() {
2996 DomHandler.removeClass(this.boxViewChild.nativeElement, 'p-focus');
2997 }
2998 ngOnDestroy() {
2999 if (this.subscription) {
3000 this.subscription.unsubscribe();
3001 }
3002 }
3003}
3004TableCheckbox.decorators = [
3005 { type: Component, args: [{
3006 selector: 'p-tableCheckbox',
3007 template: `
3008 <div class="p-checkbox p-component" (click)="onClick($event)">
3009 <div class="p-hidden-accessible">
3010 <input type="checkbox" [attr.id]="inputId" [attr.name]="name" [checked]="checked" (focus)="onFocus()" (blur)="onBlur()" [disabled]="disabled"
3011 [attr.required]="required" [attr.aria-label]="ariaLabel">
3012 </div>
3013 <div #box [ngClass]="{'p-checkbox-box p-component':true,
3014 'p-highlight':checked, 'p-disabled':disabled}" role="checkbox" [attr.aria-checked]="checked">
3015 <span class="p-checkbox-icon" [ngClass]="{'pi pi-check':checked}"></span>
3016 </div>
3017 </div>
3018 `,
3019 changeDetection: ChangeDetectionStrategy.OnPush,
3020 encapsulation: ViewEncapsulation.None
3021 },] }
3022];
3023TableCheckbox.ctorParameters = () => [
3024 { type: Table },
3025 { type: TableService },
3026 { type: ChangeDetectorRef }
3027];
3028TableCheckbox.propDecorators = {
3029 disabled: [{ type: Input }],
3030 value: [{ type: Input }],
3031 index: [{ type: Input }],
3032 inputId: [{ type: Input }],
3033 name: [{ type: Input }],
3034 required: [{ type: Input }],
3035 ariaLabel: [{ type: Input }],
3036 boxViewChild: [{ type: ViewChild, args: ['box',] }]
3037};
3038class TableHeaderCheckbox {
3039 constructor(dt, tableService, cd) {
3040 this.dt = dt;
3041 this.tableService = tableService;
3042 this.cd = cd;
3043 this.valueChangeSubscription = this.dt.tableService.valueSource$.subscribe(() => {
3044 this.checked = this.updateCheckedState();
3045 });
3046 this.selectionChangeSubscription = this.dt.tableService.selectionSource$.subscribe(() => {
3047 this.checked = this.updateCheckedState();
3048 });
3049 }
3050 ngOnInit() {
3051 this.checked = this.updateCheckedState();
3052 }
3053 onClick(event) {
3054 if (!this.disabled) {
3055 if (this.dt.value && this.dt.value.length > 0) {
3056 this.dt.toggleRowsWithCheckbox(event, !this.checked);
3057 }
3058 }
3059 DomHandler.clearSelection();
3060 }
3061 onFocus() {
3062 DomHandler.addClass(this.boxViewChild.nativeElement, 'p-focus');
3063 }
3064 onBlur() {
3065 DomHandler.removeClass(this.boxViewChild.nativeElement, 'p-focus');
3066 }
3067 isDisabled() {
3068 return this.disabled || !this.dt.value || !this.dt.value.length;
3069 }
3070 ngOnDestroy() {
3071 if (this.selectionChangeSubscription) {
3072 this.selectionChangeSubscription.unsubscribe();
3073 }
3074 if (this.valueChangeSubscription) {
3075 this.valueChangeSubscription.unsubscribe();
3076 }
3077 }
3078 updateCheckedState() {
3079 this.cd.markForCheck();
3080 if (this.dt.filteredValue) {
3081 const val = this.dt.filteredValue;
3082 return (val && val.length > 0 && this.dt.selection && this.dt.selection.length > 0 && this.isAllFilteredValuesChecked());
3083 }
3084 else {
3085 const val = this.dt.value;
3086 return (val && val.length > 0 && this.dt.selection && this.dt.selection.length > 0 && this.dt.selection.length === val.length);
3087 }
3088 }
3089 isAllFilteredValuesChecked() {
3090 if (!this.dt.filteredValue) {
3091 return false;
3092 }
3093 else {
3094 for (let rowData of this.dt.filteredValue) {
3095 if (!this.dt.isSelected(rowData)) {
3096 return false;
3097 }
3098 }
3099 return true;
3100 }
3101 }
3102}
3103TableHeaderCheckbox.decorators = [
3104 { type: Component, args: [{
3105 selector: 'p-tableHeaderCheckbox',
3106 template: `
3107 <div class="p-checkbox p-component" (click)="onClick($event)">
3108 <div class="p-hidden-accessible">
3109 <input #cb type="checkbox" [attr.id]="inputId" [attr.name]="name" [checked]="checked" (focus)="onFocus()" (blur)="onBlur()"
3110 [disabled]="isDisabled()" [attr.aria-label]="ariaLabel">
3111 </div>
3112 <div #box [ngClass]="{'p-checkbox-box':true,
3113 'p-highlight':checked, 'p-disabled': isDisabled()}" role="checkbox" [attr.aria-checked]="checked">
3114 <span class="p-checkbox-icon" [ngClass]="{'pi pi-check':checked}"></span>
3115 </div>
3116 </div>
3117 `,
3118 changeDetection: ChangeDetectionStrategy.OnPush,
3119 encapsulation: ViewEncapsulation.None
3120 },] }
3121];
3122TableHeaderCheckbox.ctorParameters = () => [
3123 { type: Table },
3124 { type: TableService },
3125 { type: ChangeDetectorRef }
3126];
3127TableHeaderCheckbox.propDecorators = {
3128 boxViewChild: [{ type: ViewChild, args: ['box',] }],
3129 disabled: [{ type: Input }],
3130 inputId: [{ type: Input }],
3131 name: [{ type: Input }],
3132 ariaLabel: [{ type: Input }]
3133};
3134class ReorderableRowHandle {
3135 constructor(el) {
3136 this.el = el;
3137 }
3138 ngAfterViewInit() {
3139 DomHandler.addClass(this.el.nativeElement, 'p-datatable-reorderablerow-handle');
3140 }
3141}
3142ReorderableRowHandle.decorators = [
3143 { type: Directive, args: [{
3144 selector: '[pReorderableRowHandle]'
3145 },] }
3146];
3147ReorderableRowHandle.ctorParameters = () => [
3148 { type: ElementRef }
3149];
3150ReorderableRowHandle.propDecorators = {
3151 index: [{ type: Input, args: ["pReorderableRowHandle",] }]
3152};
3153class ReorderableRow {
3154 constructor(dt, el, zone) {
3155 this.dt = dt;
3156 this.el = el;
3157 this.zone = zone;
3158 }
3159 ngAfterViewInit() {
3160 if (this.isEnabled()) {
3161 this.el.nativeElement.droppable = true;
3162 this.bindEvents();
3163 }
3164 }
3165 bindEvents() {
3166 this.zone.runOutsideAngular(() => {
3167 this.mouseDownListener = this.onMouseDown.bind(this);
3168 this.el.nativeElement.addEventListener('mousedown', this.mouseDownListener);
3169 this.dragStartListener = this.onDragStart.bind(this);
3170 this.el.nativeElement.addEventListener('dragstart', this.dragStartListener);
3171 this.dragEndListener = this.onDragEnd.bind(this);
3172 this.el.nativeElement.addEventListener('dragend', this.dragEndListener);
3173 this.dragOverListener = this.onDragOver.bind(this);
3174 this.el.nativeElement.addEventListener('dragover', this.dragOverListener);
3175 this.dragLeaveListener = this.onDragLeave.bind(this);
3176 this.el.nativeElement.addEventListener('dragleave', this.dragLeaveListener);
3177 });
3178 }
3179 unbindEvents() {
3180 if (this.mouseDownListener) {
3181 document.removeEventListener('mousedown', this.mouseDownListener);
3182 this.mouseDownListener = null;
3183 }
3184 if (this.dragStartListener) {
3185 document.removeEventListener('dragstart', this.dragStartListener);
3186 this.dragStartListener = null;
3187 }
3188 if (this.dragEndListener) {
3189 document.removeEventListener('dragend', this.dragEndListener);
3190 this.dragEndListener = null;
3191 }
3192 if (this.dragOverListener) {
3193 document.removeEventListener('dragover', this.dragOverListener);
3194 this.dragOverListener = null;
3195 }
3196 if (this.dragLeaveListener) {
3197 document.removeEventListener('dragleave', this.dragLeaveListener);
3198 this.dragLeaveListener = null;
3199 }
3200 }
3201 onMouseDown(event) {
3202 if (DomHandler.hasClass(event.target, 'p-datatable-reorderablerow-handle'))
3203 this.el.nativeElement.draggable = true;
3204 else
3205 this.el.nativeElement.draggable = false;
3206 }
3207 onDragStart(event) {
3208 this.dt.onRowDragStart(event, this.index);
3209 }
3210 onDragEnd(event) {
3211 this.dt.onRowDragEnd(event);
3212 this.el.nativeElement.draggable = false;
3213 }
3214 onDragOver(event) {
3215 this.dt.onRowDragOver(event, this.index, this.el.nativeElement);
3216 event.preventDefault();
3217 }
3218 onDragLeave(event) {
3219 this.dt.onRowDragLeave(event, this.el.nativeElement);
3220 }
3221 isEnabled() {
3222 return this.pReorderableRowDisabled !== true;
3223 }
3224 onDrop(event) {
3225 if (this.isEnabled() && this.dt.rowDragging) {
3226 this.dt.onRowDrop(event, this.el.nativeElement);
3227 }
3228 event.preventDefault();
3229 }
3230}
3231ReorderableRow.decorators = [
3232 { type: Directive, args: [{
3233 selector: '[pReorderableRow]'
3234 },] }
3235];
3236ReorderableRow.ctorParameters = () => [
3237 { type: Table },
3238 { type: ElementRef },
3239 { type: NgZone }
3240];
3241ReorderableRow.propDecorators = {
3242 index: [{ type: Input, args: ["pReorderableRow",] }],
3243 pReorderableRowDisabled: [{ type: Input }],
3244 onDrop: [{ type: HostListener, args: ['drop', ['$event'],] }]
3245};
3246class TableModule {
3247}
3248TableModule.decorators = [
3249 { type: NgModule, args: [{
3250 imports: [CommonModule, PaginatorModule, ScrollingModule],
3251 exports: [Table, SharedModule, SortableColumn, SelectableRow, RowToggler, ContextMenuRow, ResizableColumn, ReorderableColumn, EditableColumn, CellEditor, SortIcon, TableRadioButton, TableCheckbox, TableHeaderCheckbox, ReorderableRowHandle, ReorderableRow, SelectableRowDblClick, EditableRow, InitEditableRow, SaveEditableRow, CancelEditableRow, ScrollingModule],
3252 declarations: [Table, SortableColumn, SelectableRow, RowToggler, ContextMenuRow, ResizableColumn, ReorderableColumn, EditableColumn, CellEditor, TableBody, ScrollableView, SortIcon, TableRadioButton, TableCheckbox, TableHeaderCheckbox, ReorderableRowHandle, ReorderableRow, SelectableRowDblClick, EditableRow, InitEditableRow, SaveEditableRow, CancelEditableRow]
3253 },] }
3254];
3255
3256/**
3257 * Generated bundle index. Do not edit.
3258 */
3259
3260export { CancelEditableRow, CellEditor, ContextMenuRow, EditableColumn, EditableRow, InitEditableRow, ReorderableColumn, ReorderableRow, ReorderableRowHandle, ResizableColumn, RowToggler, SaveEditableRow, ScrollableView, SelectableRow, SelectableRowDblClick, SortIcon, SortableColumn, Table, TableBody, TableCheckbox, TableHeaderCheckbox, TableModule, TableRadioButton, TableService };
3261//# sourceMappingURL=primeng-table.js.map