@swimlane/ngx-datatable 11.1.4 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +6 -0
- package/README.md +2 -1
- package/config/deploy.js +2 -2
- package/config/karma.conf.js +5 -0
- package/config/webpack.package.js +4 -0
- package/package.json +15 -14
- package/release/components/body/body-cell.component.js.map +1 -1
- package/release/components/body/body-cell.component.metadata.json +1 -1
- package/release/components/body/body-group-header-template.directive.js.map +1 -1
- package/release/components/body/body-group-header-template.directive.metadata.json +1 -1
- package/release/components/body/body-group-header.directive.d.ts +4 -5
- package/release/components/body/body-group-header.directive.js +4 -5
- package/release/components/body/body-group-header.directive.js.map +1 -1
- package/release/components/body/body-group-header.directive.metadata.json +1 -1
- package/release/components/body/body-row-wrapper.component.js.map +1 -1
- package/release/components/body/body-row-wrapper.component.metadata.json +1 -1
- package/release/components/body/body-row.component.js +5 -1
- package/release/components/body/body-row.component.js.map +1 -1
- package/release/components/body/body-row.component.metadata.json +1 -1
- package/release/components/body/body.component.d.ts +2 -1
- package/release/components/body/body.component.js +31 -16
- package/release/components/body/body.component.js.map +1 -1
- package/release/components/body/body.component.metadata.json +1 -1
- package/release/components/body/index.js.map +1 -1
- package/release/components/body/index.metadata.json +1 -1
- package/release/components/body/progress-bar.component.js.map +1 -1
- package/release/components/body/progress-bar.component.metadata.json +1 -1
- package/release/components/body/scroller.component.d.ts +3 -2
- package/release/components/body/scroller.component.js +5 -3
- package/release/components/body/scroller.component.js.map +1 -1
- package/release/components/body/scroller.component.metadata.json +1 -1
- package/release/components/body/selection.component.js.map +1 -1
- package/release/components/body/selection.component.metadata.json +1 -1
- package/release/components/columns/column-cell.directive.js.map +1 -1
- package/release/components/columns/column-cell.directive.metadata.json +1 -1
- package/release/components/columns/column-header.directive.js.map +1 -1
- package/release/components/columns/column-header.directive.metadata.json +1 -1
- package/release/components/columns/column.directive.js.map +1 -1
- package/release/components/columns/column.directive.metadata.json +1 -1
- package/release/components/columns/index.js.map +1 -1
- package/release/components/columns/index.metadata.json +1 -1
- package/release/components/datatable.component.css +7 -2
- package/release/components/datatable.component.d.ts +8 -3
- package/release/components/datatable.component.js +29 -11
- package/release/components/datatable.component.js.map +1 -1
- package/release/components/datatable.component.metadata.json +1 -1
- package/release/components/footer/footer-template.directive.js.map +1 -1
- package/release/components/footer/footer-template.directive.metadata.json +1 -1
- package/release/components/footer/footer.component.js.map +1 -1
- package/release/components/footer/footer.component.metadata.json +1 -1
- package/release/components/footer/footer.directive.js.map +1 -1
- package/release/components/footer/footer.directive.metadata.json +1 -1
- package/release/components/footer/index.js.map +1 -1
- package/release/components/footer/index.metadata.json +1 -1
- package/release/components/footer/pager.component.js +1 -1
- package/release/components/footer/pager.component.js.map +1 -1
- package/release/components/footer/pager.component.metadata.json +1 -1
- package/release/components/header/header-cell.component.js +2 -1
- package/release/components/header/header-cell.component.js.map +1 -1
- package/release/components/header/header-cell.component.metadata.json +1 -1
- package/release/components/header/header.component.js +1 -0
- package/release/components/header/header.component.js.map +1 -1
- package/release/components/header/header.component.metadata.json +1 -1
- package/release/components/header/index.js.map +1 -1
- package/release/components/header/index.metadata.json +1 -1
- package/release/components/index.js.map +1 -1
- package/release/components/index.metadata.json +1 -1
- package/release/components/row-detail/index.js.map +1 -1
- package/release/components/row-detail/index.metadata.json +1 -1
- package/release/components/row-detail/row-detail-template.directive.js.map +1 -1
- package/release/components/row-detail/row-detail-template.directive.metadata.json +1 -1
- package/release/components/row-detail/row-detail.directive.js.map +1 -1
- package/release/components/row-detail/row-detail.directive.metadata.json +1 -1
- package/release/datatable.module.d.ts +0 -1
- package/release/datatable.module.js +2 -2
- package/release/datatable.module.js.map +1 -1
- package/release/datatable.module.metadata.json +1 -1
- package/release/directives/draggable.directive.js +3 -3
- package/release/directives/draggable.directive.js.map +1 -1
- package/release/directives/draggable.directive.metadata.json +1 -1
- package/release/directives/index.js.map +1 -1
- package/release/directives/index.metadata.json +1 -1
- package/release/directives/long-press.directive.js +3 -3
- package/release/directives/long-press.directive.js.map +1 -1
- package/release/directives/long-press.directive.metadata.json +1 -1
- package/release/directives/orderable.directive.js.map +1 -1
- package/release/directives/orderable.directive.metadata.json +1 -1
- package/release/directives/resizeable.directive.d.ts +3 -2
- package/release/directives/resizeable.directive.js +13 -8
- package/release/directives/resizeable.directive.js.map +1 -1
- package/release/directives/resizeable.directive.metadata.json +1 -1
- package/release/directives/visibility.directive.js.map +1 -1
- package/release/directives/visibility.directive.metadata.json +1 -1
- package/release/events.d.ts +1 -0
- package/release/events.js +1 -0
- package/release/events.js.map +1 -1
- package/release/events.metadata.json +1 -1
- package/release/index.css +8 -3
- package/release/index.d.ts +1 -0
- package/release/index.js +198 -14804
- package/release/index.js.map +1 -1
- package/release/index.metadata.json +1 -1
- package/release/index.min.js +1 -1
- package/release/index.min.js.map +1 -1
- package/release/services/dimensions-helper.service.d.ts +7 -0
- package/release/services/dimensions-helper.service.js +26 -0
- package/release/services/dimensions-helper.service.js.map +1 -0
- package/release/services/dimensions-helper.service.metadata.json +1 -0
- package/release/services/index.d.ts +1 -0
- package/release/services/index.js +1 -0
- package/release/services/index.js.map +1 -1
- package/release/services/index.metadata.json +1 -1
- package/release/services/scrollbar-helper.service.js.map +1 -1
- package/release/services/scrollbar-helper.service.metadata.json +1 -1
- package/release/types/click.type.js.map +1 -1
- package/release/types/click.type.metadata.json +1 -1
- package/release/types/column-mode.type.js.map +1 -1
- package/release/types/column-mode.type.metadata.json +1 -1
- package/release/types/contextmenu.type.js.map +1 -1
- package/release/types/contextmenu.type.metadata.json +1 -1
- package/release/types/index.js.map +1 -1
- package/release/types/index.metadata.json +1 -1
- package/release/types/selection.type.js.map +1 -1
- package/release/types/selection.type.metadata.json +1 -1
- package/release/types/sort-direction.type.js.map +1 -1
- package/release/types/sort-direction.type.metadata.json +1 -1
- package/release/types/sort-prop-dir.type.js.map +1 -1
- package/release/types/sort-prop-dir.type.metadata.json +1 -1
- package/release/types/sort.type.js.map +1 -1
- package/release/types/sort.type.metadata.json +1 -1
- package/release/types/table-column.type.js.map +1 -1
- package/release/types/table-column.type.metadata.json +1 -1
- package/release/utils/camel-case.js.map +1 -1
- package/release/utils/camel-case.metadata.json +1 -1
- package/release/utils/column-helper.js.map +1 -1
- package/release/utils/column-helper.metadata.json +1 -1
- package/release/utils/column-prop-getters.js.map +1 -1
- package/release/utils/column-prop-getters.metadata.json +1 -1
- package/release/utils/column.d.ts +0 -4
- package/release/utils/column.js +0 -10
- package/release/utils/column.js.map +1 -1
- package/release/utils/column.metadata.json +1 -1
- package/release/utils/elm-from-point.js.map +1 -1
- package/release/utils/elm-from-point.metadata.json +1 -1
- package/release/utils/id.js.map +1 -1
- package/release/utils/id.metadata.json +1 -1
- package/release/utils/index.js.map +1 -1
- package/release/utils/index.metadata.json +1 -1
- package/release/utils/keys.js.map +1 -1
- package/release/utils/keys.metadata.json +1 -1
- package/release/utils/math.js +1 -1
- package/release/utils/math.js.map +1 -1
- package/release/utils/math.metadata.json +1 -1
- package/release/utils/prefixes.js +4 -6
- package/release/utils/prefixes.js.map +1 -1
- package/release/utils/prefixes.metadata.json +1 -1
- package/release/utils/row-height-cache.js.map +1 -1
- package/release/utils/row-height-cache.metadata.json +1 -1
- package/release/utils/selection.js.map +1 -1
- package/release/utils/selection.metadata.json +1 -1
- package/release/utils/sort.d.ts +2 -1
- package/release/utils/sort.js +6 -2
- package/release/utils/sort.js.map +1 -1
- package/release/utils/sort.metadata.json +1 -1
- package/release/utils/throttle.js.map +1 -1
- package/release/utils/throttle.metadata.json +1 -1
- package/release/utils/translate.js.map +1 -1
- package/release/utils/translate.metadata.json +1 -1
- package/src/components/body/body-group-header.directive.ts +5 -6
- package/src/components/body/body-row.component.ts +5 -5
- package/src/components/body/body.component.ts +46 -36
- package/src/components/body/scroller.component.ts +7 -5
- package/src/components/body/selection.component.ts +1 -1
- package/src/components/datatable.component.scss +14 -1
- package/src/components/datatable.component.spec.ts +383 -220
- package/src/components/datatable.component.ts +26 -13
- package/src/components/footer/footer.component.spec.ts +329 -47
- package/src/components/footer/pager.component.ts +10 -0
- package/src/components/header/header-cell.component.ts +2 -1
- package/src/components/header/header.component.ts +1 -0
- package/src/datatable.module.ts +6 -3
- package/src/directives/draggable.directive.ts +3 -2
- package/src/directives/long-press.directive.ts +3 -3
- package/src/directives/resizeable.directive.ts +11 -7
- package/src/events.ts +1 -0
- package/src/index.ts +1 -0
- package/src/services/dimensions-helper.service.ts +14 -0
- package/src/services/index.ts +1 -0
- package/src/utils/column-prop-getters.spec.ts +44 -0
- package/src/utils/column.ts +0 -12
- package/src/utils/facade/browser.ts +26 -0
- package/src/utils/math.ts +1 -1
- package/src/utils/sort.ts +7 -3
- package/test/index.ts +1 -0
- package/test/jasmine-matchers.d.ts +12 -0
- package/test/jasmine-matchers.ts +70 -0
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
HostListener, ContentChildren, OnInit, QueryList, AfterViewInit,
|
|
4
4
|
HostBinding, ContentChild, TemplateRef, IterableDiffer,
|
|
5
5
|
DoCheck, KeyValueDiffers, KeyValueDiffer, ViewEncapsulation,
|
|
6
|
-
ChangeDetectionStrategy, ChangeDetectorRef
|
|
6
|
+
ChangeDetectionStrategy, ChangeDetectorRef, SkipSelf
|
|
7
7
|
} from '@angular/core';
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
forceFillColumnWidths, adjustColumnWidths, sortRows,
|
|
11
11
|
setColumnDefaults, throttleable, translateTemplates
|
|
12
12
|
} from '../utils';
|
|
13
|
-
import { ScrollbarHelper } from '../services';
|
|
13
|
+
import { ScrollbarHelper, DimensionsHelper } from '../services';
|
|
14
14
|
import { ColumnMode, SortType, SelectionType, TableColumn, ContextmenuType } from '../types';
|
|
15
15
|
import { DataTableBodyComponent } from './body';
|
|
16
16
|
import { DatatableGroupHeaderDirective } from './body/body-group-header.directive';
|
|
@@ -55,6 +55,7 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
|
|
55
55
|
[groupExpansionDefault]="groupExpansionDefault"
|
|
56
56
|
[scrollbarV]="scrollbarV"
|
|
57
57
|
[scrollbarH]="scrollbarH"
|
|
58
|
+
[virtualization]="virtualization"
|
|
58
59
|
[loadingIndicator]="loadingIndicator"
|
|
59
60
|
[externalPaging]="externalPaging"
|
|
60
61
|
[rowHeight]="rowHeight"
|
|
@@ -114,11 +115,13 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
114
115
|
@Input() set rows(val: any) {
|
|
115
116
|
this._rows = val;
|
|
116
117
|
|
|
118
|
+
if (val) {
|
|
119
|
+
this._internalRows = [...val];
|
|
120
|
+
}
|
|
121
|
+
|
|
117
122
|
// auto sort on new updates
|
|
118
123
|
if (!this.externalSorting) {
|
|
119
|
-
this._internalRows = sortRows(
|
|
120
|
-
} else {
|
|
121
|
-
this._internalRows = [...val];
|
|
124
|
+
this._internalRows = sortRows(this._internalRows, this._internalColumns, this.sorts);
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
// recalculate sizes/etc
|
|
@@ -304,7 +307,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
304
307
|
*
|
|
305
308
|
* - `single`
|
|
306
309
|
* - `multi`
|
|
307
|
-
* - `
|
|
310
|
+
* - `checkbox`
|
|
308
311
|
* - `multiClick`
|
|
309
312
|
* - `cell`
|
|
310
313
|
*
|
|
@@ -420,6 +423,11 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
420
423
|
*/
|
|
421
424
|
@Input() selectAllRowsOnPage = false;
|
|
422
425
|
|
|
426
|
+
/**
|
|
427
|
+
* A flag for row virtualization on / off
|
|
428
|
+
*/
|
|
429
|
+
@Input() virtualization: boolean = true;
|
|
430
|
+
|
|
423
431
|
/**
|
|
424
432
|
* Body was scrolled typically in a `scrollbarV:true` scenario.
|
|
425
433
|
*/
|
|
@@ -606,7 +614,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
606
614
|
* Returns if all rows are selected.
|
|
607
615
|
*/
|
|
608
616
|
get allRowsSelected(): boolean {
|
|
609
|
-
let allRowsSelected = (this.selected.length === this.rows.length);
|
|
617
|
+
let allRowsSelected = (this.rows && this.selected && this.selected.length === this.rows.length);
|
|
610
618
|
|
|
611
619
|
if (this.selectAllRowsOnPage) {
|
|
612
620
|
const indexes = this.bodyComponent.indexes;
|
|
@@ -637,7 +645,8 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
637
645
|
_columnTemplates: QueryList<DataTableColumnDirective>;
|
|
638
646
|
|
|
639
647
|
constructor(
|
|
640
|
-
private scrollbarHelper: ScrollbarHelper,
|
|
648
|
+
@SkipSelf() private scrollbarHelper: ScrollbarHelper,
|
|
649
|
+
@SkipSelf() private dimensionsHelper: DimensionsHelper,
|
|
641
650
|
private cd: ChangeDetectorRef,
|
|
642
651
|
element: ElementRef,
|
|
643
652
|
differs: KeyValueDiffers) {
|
|
@@ -664,11 +673,15 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
664
673
|
*/
|
|
665
674
|
ngAfterViewInit(): void {
|
|
666
675
|
if (!this.externalSorting) {
|
|
667
|
-
this._internalRows = sortRows(this.
|
|
676
|
+
this._internalRows = sortRows(this._internalRows, this._internalColumns, this.sorts);
|
|
668
677
|
}
|
|
669
678
|
|
|
670
679
|
// this has to be done to prevent the change detection
|
|
671
680
|
// tree from freaking out because we are readjusting
|
|
681
|
+
if (typeof requestAnimationFrame === 'undefined') {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
|
|
672
685
|
requestAnimationFrame(() => {
|
|
673
686
|
this.recalculate();
|
|
674
687
|
|
|
@@ -710,7 +723,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
710
723
|
|
|
711
724
|
/**
|
|
712
725
|
* Creates a map with the data grouped by the user choice of grouping index
|
|
713
|
-
*
|
|
726
|
+
*
|
|
714
727
|
* @param originalArray the original array passed via parameter
|
|
715
728
|
* @param groupByIndex the index of the column to group the data by
|
|
716
729
|
*/
|
|
@@ -743,7 +756,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
743
756
|
ngDoCheck(): void {
|
|
744
757
|
if (this.rowDiffer.diff(this.rows)) {
|
|
745
758
|
if (!this.externalSorting) {
|
|
746
|
-
this._internalRows = sortRows(this.
|
|
759
|
+
this._internalRows = sortRows(this._internalRows, this._internalColumns, this.sorts);
|
|
747
760
|
} else {
|
|
748
761
|
this._internalRows = [...this.rows];
|
|
749
762
|
}
|
|
@@ -809,7 +822,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
809
822
|
*
|
|
810
823
|
*/
|
|
811
824
|
recalculateDims(): void {
|
|
812
|
-
const dims = this.
|
|
825
|
+
const dims = this.dimensionsHelper.getDimensions(this.element);
|
|
813
826
|
this._innerWidth = Math.floor(dims.width);
|
|
814
827
|
|
|
815
828
|
if (this.scrollbarV) {
|
|
@@ -1005,7 +1018,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
1005
1018
|
// the rows again on the 'push' detection...
|
|
1006
1019
|
if (this.externalSorting === false) {
|
|
1007
1020
|
// don't use normal setter so we don't resort
|
|
1008
|
-
this._internalRows = sortRows(this.
|
|
1021
|
+
this._internalRows = sortRows(this._internalRows, this._internalColumns, sorts);
|
|
1009
1022
|
}
|
|
1010
1023
|
|
|
1011
1024
|
this.sorts = sorts;
|
|
@@ -1,76 +1,358 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
Component,
|
|
3
|
+
DebugElement,
|
|
4
|
+
Input,
|
|
5
|
+
Output,
|
|
6
|
+
EventEmitter,
|
|
7
|
+
ViewChild,
|
|
8
|
+
TemplateRef
|
|
9
|
+
} from '@angular/core';
|
|
10
|
+
import { async, TestBed, ComponentFixture } from '@angular/core/testing';
|
|
11
|
+
import { By } from '@angular/platform-browser';
|
|
5
12
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
import { DataTableFooterComponent, DataTablePagerComponent } from '.';
|
|
14
|
+
import { addMatchers } from '../../../test';
|
|
15
|
+
|
|
16
|
+
let fixture: ComponentFixture<TestFixtureComponent>;
|
|
17
|
+
let component: TestFixtureComponent;
|
|
18
|
+
let page: Page;
|
|
11
19
|
|
|
12
20
|
describe('DataTableFooterComponent', () => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
beforeAll(addMatchers);
|
|
22
|
+
|
|
23
|
+
beforeEach(async(setupTest));
|
|
24
|
+
|
|
25
|
+
describe('div.datatable-footer-inner', () => {
|
|
26
|
+
it(`should have a height`, () => {
|
|
27
|
+
component.footerHeight = 123;
|
|
28
|
+
page.detectChangesAndRunQueries();
|
|
29
|
+
|
|
30
|
+
expect(page.datatableFooterInner.nativeElement.style.height).toEqual(
|
|
31
|
+
'123px'
|
|
32
|
+
);
|
|
24
33
|
});
|
|
25
|
-
});
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
it('should have `.selected-count` class when selectedMessage is set', () => {
|
|
36
|
+
component.selectedMessage = 'selected';
|
|
37
|
+
component.selectedCount = 1;
|
|
38
|
+
page.detectChangesAndRunQueries();
|
|
39
|
+
|
|
40
|
+
expect(page.datatableFooterInner.nativeElement).toHaveCssClass(
|
|
41
|
+
'selected-count'
|
|
42
|
+
);
|
|
32
43
|
});
|
|
33
|
-
}));
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
it('should not have `.selected-count` class if selectedMessage is not set', () => {
|
|
46
|
+
component.selectedMessage = undefined;
|
|
47
|
+
page.detectChangesAndRunQueries();
|
|
48
|
+
|
|
49
|
+
expect(page.datatableFooterInner.nativeElement).not.toHaveCssClass(
|
|
50
|
+
'selected-count'
|
|
51
|
+
);
|
|
38
52
|
});
|
|
39
53
|
});
|
|
40
54
|
|
|
41
|
-
describe('when
|
|
55
|
+
describe('when there is no template', () => {
|
|
56
|
+
it('should not render a template', () => {
|
|
57
|
+
component.footerTemplate = undefined;
|
|
58
|
+
page.detectChangesAndRunQueries();
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
component.rowCount = 9;
|
|
60
|
+
expect(page.templateList).toBeNull();
|
|
61
|
+
});
|
|
46
62
|
|
|
63
|
+
it('should display the selected count and total if selectedMessage set', () => {
|
|
64
|
+
component.footerTemplate = undefined;
|
|
47
65
|
component.selectedMessage = 'selected';
|
|
48
|
-
component.selectedCount =
|
|
66
|
+
component.selectedCount = 7;
|
|
67
|
+
component.rowCount = 10;
|
|
68
|
+
component.totalMessage = 'total';
|
|
69
|
+
page.detectChangesAndRunQueries();
|
|
70
|
+
|
|
71
|
+
expect(page.pageCount.nativeElement.innerText).toEqual(
|
|
72
|
+
'7 selected / 10 total'
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should display only the total if selectedMessage is not set', () => {
|
|
77
|
+
component.footerTemplate = undefined;
|
|
78
|
+
component.selectedMessage = undefined;
|
|
79
|
+
component.rowCount = 100;
|
|
80
|
+
component.totalMessage = 'total';
|
|
81
|
+
page.detectChangesAndRunQueries();
|
|
82
|
+
|
|
83
|
+
expect(page.pageCount.nativeElement.innerText).toEqual('100 total');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should render a DataTablePagerComponent', () => {
|
|
87
|
+
component.footerTemplate = undefined;
|
|
88
|
+
page.detectChangesAndRunQueries();
|
|
89
|
+
|
|
90
|
+
expect(page.datatablePager).not.toBeNull();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should propagate page change events upward from the DataTablePagerComponent', () => {
|
|
94
|
+
component.footerTemplate = undefined;
|
|
95
|
+
page.detectChangesAndRunQueries();
|
|
96
|
+
const spy = spyOn(component, 'onPageEvent');
|
|
97
|
+
const pageChangeEvent = { page: 7 };
|
|
98
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
99
|
+
page.datatablePager.componentInstance;
|
|
100
|
+
// mimic the act of changing the page through the datatable pager
|
|
101
|
+
datatablePagerComponent.change.emit(pageChangeEvent);
|
|
102
|
+
|
|
103
|
+
expect(spy).toHaveBeenCalledWith(pageChangeEvent);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should bind to DataTablePagerComponent pagerLeftArrowIcon input', () => {
|
|
107
|
+
component.pagerLeftArrowIcon = 'pager-left-arrow-icon';
|
|
108
|
+
page.detectChangesAndRunQueries();
|
|
109
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
110
|
+
page.datatablePager.componentInstance;
|
|
111
|
+
|
|
112
|
+
expect(datatablePagerComponent.pagerLeftArrowIcon).toBe(
|
|
113
|
+
component.pagerLeftArrowIcon
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should bind to DataTablePagerComponent pagerRightArrowIcon input', () => {
|
|
118
|
+
component.pagerRightArrowIcon = 'pager-right-arrow-icon';
|
|
119
|
+
page.detectChangesAndRunQueries();
|
|
120
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
121
|
+
page.datatablePager.componentInstance;
|
|
122
|
+
|
|
123
|
+
expect(datatablePagerComponent.pagerRightArrowIcon).toBe(
|
|
124
|
+
component.pagerRightArrowIcon
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should bind to DataTablePagerComponent pagerNextIcon input', () => {
|
|
129
|
+
component.pagerNextIcon = 'pager-next-icon';
|
|
130
|
+
page.detectChangesAndRunQueries();
|
|
131
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
132
|
+
page.datatablePager.componentInstance;
|
|
49
133
|
|
|
50
|
-
|
|
134
|
+
expect(datatablePagerComponent.pagerNextIcon).toBe(
|
|
135
|
+
component.pagerNextIcon
|
|
136
|
+
);
|
|
51
137
|
});
|
|
52
138
|
|
|
53
|
-
it('
|
|
54
|
-
|
|
139
|
+
it('should bind to DataTablePagerComponent pagerPreviousIcon input', () => {
|
|
140
|
+
component.pagerPreviousIcon = 'pager-previous-icon';
|
|
141
|
+
page.detectChangesAndRunQueries();
|
|
142
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
143
|
+
page.datatablePager.componentInstance;
|
|
55
144
|
|
|
56
|
-
expect(
|
|
145
|
+
expect(datatablePagerComponent.pagerPreviousIcon).toBe(
|
|
146
|
+
component.pagerPreviousIcon
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should bind to DataTablePagerComponent size input', () => {
|
|
151
|
+
component.pageSize = 4;
|
|
152
|
+
page.detectChangesAndRunQueries();
|
|
153
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
154
|
+
page.datatablePager.componentInstance;
|
|
155
|
+
|
|
156
|
+
expect(datatablePagerComponent.size).toBe(component.pageSize);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should bind to DataTablePagerComponent count input', () => {
|
|
160
|
+
component.rowCount = 40;
|
|
161
|
+
page.detectChangesAndRunQueries();
|
|
162
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
163
|
+
page.datatablePager.componentInstance;
|
|
164
|
+
|
|
165
|
+
expect(datatablePagerComponent.count).toBe(component.rowCount);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should bind to DataTablePagerComponent page input', () => {
|
|
169
|
+
component.offset = 200;
|
|
170
|
+
page.detectChangesAndRunQueries();
|
|
171
|
+
const datatablePagerComponent: DataTablePagerComponent =
|
|
172
|
+
page.datatablePager.componentInstance;
|
|
173
|
+
|
|
174
|
+
expect(datatablePagerComponent.page).toBe(201);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should show & hide the DataTablePagerComponent', () => {
|
|
178
|
+
component.rowCount = 200;
|
|
179
|
+
component.pageSize = 5;
|
|
180
|
+
page.detectChangesAndRunQueries();
|
|
181
|
+
|
|
182
|
+
expect(page.datatablePager.nativeElement.hidden).toBe(
|
|
183
|
+
false,
|
|
184
|
+
'DataTablePagerComponent should be hidden'
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
component.rowCount = 1;
|
|
188
|
+
component.pageSize = 2;
|
|
189
|
+
page.detectChangesAndRunQueries();
|
|
190
|
+
|
|
191
|
+
expect(page.datatablePager.nativeElement.hidden).toBe(
|
|
192
|
+
true,
|
|
193
|
+
'DataTablePagerComponent should not be hidden'
|
|
194
|
+
);
|
|
57
195
|
});
|
|
58
196
|
});
|
|
59
197
|
|
|
60
|
-
describe('when
|
|
198
|
+
describe('when there is a template', () => {
|
|
199
|
+
it('should not render div.page-count or DatatablePagerComponent', () => {
|
|
200
|
+
component.footerTemplate = { template: component.testTemplate };
|
|
201
|
+
page.detectChangesAndRunQueries();
|
|
61
202
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
203
|
+
expect(page.pageCount).toBeNull();
|
|
204
|
+
expect(page.datatablePager).toBeNull();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('should render the template', () => {
|
|
208
|
+
page.detectChangesAndRunQueries();
|
|
209
|
+
component.footerTemplate = { template: component.testTemplate };
|
|
210
|
+
page.detectChangesAndRunQueries();
|
|
66
211
|
|
|
67
|
-
|
|
212
|
+
expect(page.templateList).not.toBeNull();
|
|
68
213
|
});
|
|
69
214
|
|
|
70
|
-
it('
|
|
71
|
-
|
|
215
|
+
it('should give the template proper context', () => {
|
|
216
|
+
component.footerTemplate = { template: component.testTemplate };
|
|
217
|
+
component.rowCount = 12;
|
|
218
|
+
component.pageSize = 1;
|
|
219
|
+
component.selectedCount = 4;
|
|
220
|
+
component.offset = 0;
|
|
221
|
+
page.detectChangesAndRunQueries();
|
|
222
|
+
const listItems = page.templateList.queryAll(By.css('li'));
|
|
72
223
|
|
|
73
|
-
expect(
|
|
224
|
+
expect(listItems[0].nativeElement).toHaveText('rowCount 12');
|
|
225
|
+
expect(listItems[1].nativeElement).toHaveText('pageSize 1');
|
|
226
|
+
expect(listItems[2].nativeElement).toHaveText('selectedCount 4');
|
|
227
|
+
expect(listItems[3].nativeElement).toHaveText('curPage 1');
|
|
228
|
+
expect(listItems[4].nativeElement).toHaveText('offset 0');
|
|
74
229
|
});
|
|
75
230
|
});
|
|
76
231
|
});
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* we test DatatableFooterComponent by embedding it in a
|
|
235
|
+
* test host component
|
|
236
|
+
*/
|
|
237
|
+
@Component({
|
|
238
|
+
template: `
|
|
239
|
+
<datatable-footer
|
|
240
|
+
[rowCount]="rowCount"
|
|
241
|
+
[pageSize]="pageSize"
|
|
242
|
+
[offset]="offset"
|
|
243
|
+
[footerHeight]="footerHeight"
|
|
244
|
+
[footerTemplate]="footerTemplate"
|
|
245
|
+
[totalMessage]="totalMessage"
|
|
246
|
+
[pagerLeftArrowIcon]="pagerLeftArrowIcon"
|
|
247
|
+
[pagerRightArrowIcon]="pagerRightArrowIcon"
|
|
248
|
+
[pagerPreviousIcon]="pagerPreviousIcon"
|
|
249
|
+
[selectedCount]="selectedCount"
|
|
250
|
+
[selectedMessage]="selectedMessage"
|
|
251
|
+
[pagerNextIcon]="pagerNextIcon"
|
|
252
|
+
(page)="onPageEvent($event)">
|
|
253
|
+
</datatable-footer>
|
|
254
|
+
|
|
255
|
+
<ng-template
|
|
256
|
+
#testTemplate
|
|
257
|
+
let-rowCount="rowCount"
|
|
258
|
+
let-pageSize="pageSize"
|
|
259
|
+
let-selectedCount="selectedCount"
|
|
260
|
+
let-curPage="curPage"
|
|
261
|
+
let-offset="offset">
|
|
262
|
+
<ul id="template-list">
|
|
263
|
+
<li>rowCount {{rowCount}}</li>
|
|
264
|
+
<li>pageSize {{pageSize}}</li>
|
|
265
|
+
<li>selectedCount {{selectedCount}}</li>
|
|
266
|
+
<li>curPage {{curPage}}</li>
|
|
267
|
+
<li>offset {{offset}}</li>
|
|
268
|
+
</ul>
|
|
269
|
+
</ng-template>
|
|
270
|
+
`
|
|
271
|
+
})
|
|
272
|
+
class TestFixtureComponent {
|
|
273
|
+
footerHeight: number;
|
|
274
|
+
rowCount: number = 100;
|
|
275
|
+
pageSize = 1;
|
|
276
|
+
offset = 0;
|
|
277
|
+
pagerLeftArrowIcon: string;
|
|
278
|
+
pagerRightArrowIcon: string;
|
|
279
|
+
pagerPreviousIcon: string;
|
|
280
|
+
pagerNextIcon: string;
|
|
281
|
+
totalMessage: string;
|
|
282
|
+
footerTemplate: { template: TemplateRef<any> };
|
|
283
|
+
selectedCount: number;
|
|
284
|
+
selectedMessage: string;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* establishes a reference to a test template that can
|
|
288
|
+
* selectively be passed to the DatatableFooterComponent
|
|
289
|
+
* in these unit tests
|
|
290
|
+
*/
|
|
291
|
+
@ViewChild('testTemplate', { read: TemplateRef })
|
|
292
|
+
testTemplate: TemplateRef<any>;
|
|
293
|
+
|
|
294
|
+
onPageEvent() {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* we use a mock DataTablePagerComponent when testing
|
|
301
|
+
* the DataTableFooterComponent
|
|
302
|
+
*/
|
|
303
|
+
@Component({
|
|
304
|
+
selector: 'datatable-pager',
|
|
305
|
+
template: ''
|
|
306
|
+
})
|
|
307
|
+
class DataTablePagerComponentMock {
|
|
308
|
+
@Input() pagerLeftArrowIcon: string;
|
|
309
|
+
@Input() pagerRightArrowIcon: string;
|
|
310
|
+
@Input() pagerPreviousIcon: string;
|
|
311
|
+
@Input() pagerNextIcon: string;
|
|
312
|
+
@Input() page: number;
|
|
313
|
+
@Input() size: number;
|
|
314
|
+
@Input() count: number;
|
|
315
|
+
|
|
316
|
+
@Output() change: EventEmitter<any> = new EventEmitter();
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function setupTest() {
|
|
320
|
+
return TestBed.configureTestingModule({
|
|
321
|
+
declarations: [
|
|
322
|
+
TestFixtureComponent,
|
|
323
|
+
DataTableFooterComponent,
|
|
324
|
+
DataTablePagerComponentMock
|
|
325
|
+
]
|
|
326
|
+
})
|
|
327
|
+
.compileComponents()
|
|
328
|
+
.then(() => {
|
|
329
|
+
fixture = TestBed.createComponent(TestFixtureComponent);
|
|
330
|
+
component = fixture.componentInstance;
|
|
331
|
+
page = new Page();
|
|
332
|
+
page.detectChangesAndRunQueries();
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* a Page is a collection of references to DebugElements. it
|
|
338
|
+
* makes for cleaner testing
|
|
339
|
+
*/
|
|
340
|
+
class Page {
|
|
341
|
+
datatableFooter: DebugElement;
|
|
342
|
+
datatableFooterInner: DebugElement;
|
|
343
|
+
templateList: DebugElement;
|
|
344
|
+
pageCount: DebugElement;
|
|
345
|
+
datatablePager: DebugElement;
|
|
346
|
+
|
|
347
|
+
detectChangesAndRunQueries() {
|
|
348
|
+
fixture.detectChanges();
|
|
349
|
+
|
|
350
|
+
const de = fixture.debugElement;
|
|
351
|
+
|
|
352
|
+
this.datatableFooter = de.query(By.css('datatable-footer'));
|
|
353
|
+
this.datatableFooterInner = de.query(By.css('.datatable-footer-inner'));
|
|
354
|
+
this.templateList = de.query(By.css('#template-list'));
|
|
355
|
+
this.pageCount = de.query(By.css('.page-count'));
|
|
356
|
+
this.datatablePager = de.query(By.css('datatable-pager'));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
<ul class="pager">
|
|
9
9
|
<li [class.disabled]="!canPrevious()">
|
|
10
10
|
<a
|
|
11
|
+
role="button"
|
|
12
|
+
aria-label="go to first page"
|
|
11
13
|
href="javascript:void(0)"
|
|
12
14
|
(click)="selectPage(1)">
|
|
13
15
|
<i class="{{pagerPreviousIcon}}"></i>
|
|
@@ -15,12 +17,16 @@ import {
|
|
|
15
17
|
</li>
|
|
16
18
|
<li [class.disabled]="!canPrevious()">
|
|
17
19
|
<a
|
|
20
|
+
role="button"
|
|
21
|
+
aria-label="go to previous page"
|
|
18
22
|
href="javascript:void(0)"
|
|
19
23
|
(click)="prevPage()">
|
|
20
24
|
<i class="{{pagerLeftArrowIcon}}"></i>
|
|
21
25
|
</a>
|
|
22
26
|
</li>
|
|
23
27
|
<li
|
|
28
|
+
role="button"
|
|
29
|
+
[attr.aria-label]="'page ' + pg.number"
|
|
24
30
|
class="pages"
|
|
25
31
|
*ngFor="let pg of pages"
|
|
26
32
|
[class.active]="pg.number === page">
|
|
@@ -32,6 +38,8 @@ import {
|
|
|
32
38
|
</li>
|
|
33
39
|
<li [class.disabled]="!canNext()">
|
|
34
40
|
<a
|
|
41
|
+
role="button"
|
|
42
|
+
aria-label="go to next page"
|
|
35
43
|
href="javascript:void(0)"
|
|
36
44
|
(click)="nextPage()">
|
|
37
45
|
<i class="{{pagerRightArrowIcon}}"></i>
|
|
@@ -39,6 +47,8 @@ import {
|
|
|
39
47
|
</li>
|
|
40
48
|
<li [class.disabled]="!canNext()">
|
|
41
49
|
<a
|
|
50
|
+
role="button"
|
|
51
|
+
aria-label="go to last page"
|
|
42
52
|
href="javascript:void(0)"
|
|
43
53
|
(click)="selectPage(totalPages)">
|
|
44
54
|
<i class="{{pagerNextIcon}}"></i>
|
|
@@ -9,7 +9,7 @@ import { MouseEvent } from '../../events';
|
|
|
9
9
|
@Component({
|
|
10
10
|
selector: 'datatable-header-cell',
|
|
11
11
|
template: `
|
|
12
|
-
<div>
|
|
12
|
+
<div class="datatable-header-cell-template-wrap">
|
|
13
13
|
<label
|
|
14
14
|
*ngIf="isCheckboxable"
|
|
15
15
|
class="datatable-checkbox">
|
|
@@ -79,6 +79,7 @@ export class DataTableHeaderCellComponent {
|
|
|
79
79
|
@Input() set sorts(val: any[]) {
|
|
80
80
|
this._sorts = val;
|
|
81
81
|
this.sortDir = this.calcSortDir(val);
|
|
82
|
+
this.cellContext.sortDir = this.sortDir;
|
|
82
83
|
this.sortClass = this.calcSortClass(this.sortDir);
|
|
83
84
|
this.cd.markForCheck();
|
|
84
85
|
}
|
|
@@ -101,6 +101,7 @@ export class DataTableHeaderComponent {
|
|
|
101
101
|
const colsByPin = columnsByPin(val);
|
|
102
102
|
this._columnsByPin = columnsByPinArr(val);
|
|
103
103
|
this._columnGroupWidths = columnGroupWidths(colsByPin, val);
|
|
104
|
+
this.setStylesByGroup();
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
get columns(): any[] {
|
package/src/datatable.module.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { NgModule } from '@angular/core';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
|
-
import 'rxjs/add/observable/fromEvent';
|
|
4
3
|
|
|
5
4
|
import {
|
|
6
5
|
DatatableComponent,
|
|
@@ -34,14 +33,18 @@ import {
|
|
|
34
33
|
DraggableDirective
|
|
35
34
|
} from './directives';
|
|
36
35
|
|
|
37
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
ScrollbarHelper,
|
|
38
|
+
DimensionsHelper
|
|
39
|
+
} from './services';
|
|
38
40
|
|
|
39
41
|
@NgModule({
|
|
40
42
|
imports: [
|
|
41
43
|
CommonModule
|
|
42
44
|
],
|
|
43
45
|
providers: [
|
|
44
|
-
ScrollbarHelper
|
|
46
|
+
ScrollbarHelper,
|
|
47
|
+
DimensionsHelper
|
|
45
48
|
],
|
|
46
49
|
declarations: [
|
|
47
50
|
DataTableFooterTemplateDirective,
|
|
@@ -5,6 +5,7 @@ import { Observable } from 'rxjs/Observable';
|
|
|
5
5
|
import { Subscription } from 'rxjs/Subscription';
|
|
6
6
|
import { takeUntil } from 'rxjs/operators';
|
|
7
7
|
import { MouseEvent } from '../events';
|
|
8
|
+
import { fromEvent } from 'rxjs/observable/fromEvent';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Draggable Directive for Angular2
|
|
@@ -70,11 +71,11 @@ export class DraggableDirective implements OnDestroy, OnChanges {
|
|
|
70
71
|
|
|
71
72
|
const mouseDownPos = { x: event.clientX, y: event.clientY };
|
|
72
73
|
|
|
73
|
-
const mouseup =
|
|
74
|
+
const mouseup = fromEvent(document, 'mouseup');
|
|
74
75
|
this.subscription = mouseup
|
|
75
76
|
.subscribe((ev: MouseEvent) => this.onMouseup(ev));
|
|
76
77
|
|
|
77
|
-
const mouseMoveSub =
|
|
78
|
+
const mouseMoveSub = fromEvent(document, 'mousemove')
|
|
78
79
|
.pipe(takeUntil(mouseup))
|
|
79
80
|
.subscribe((ev: MouseEvent) => this.move(ev, mouseDownPos));
|
|
80
81
|
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import { Observable } from 'rxjs/Observable';
|
|
6
6
|
import { Subscription } from 'rxjs/Subscription';
|
|
7
7
|
import { takeUntil } from 'rxjs/operators';
|
|
8
|
-
|
|
8
|
+
import { fromEvent } from 'rxjs/observable/fromEvent';
|
|
9
9
|
import { MouseEvent } from '../events';
|
|
10
10
|
|
|
11
11
|
@Directive({ selector: '[long-press]' })
|
|
@@ -50,7 +50,7 @@ export class LongPressDirective implements OnDestroy {
|
|
|
50
50
|
this.pressing = true;
|
|
51
51
|
this.isLongPressing = false;
|
|
52
52
|
|
|
53
|
-
const mouseup =
|
|
53
|
+
const mouseup = fromEvent(document, 'mouseup');
|
|
54
54
|
this.subscription = mouseup.subscribe((ev: MouseEvent) => this.onMouseup());
|
|
55
55
|
|
|
56
56
|
this.timeout = setTimeout(() => {
|
|
@@ -61,7 +61,7 @@ export class LongPressDirective implements OnDestroy {
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
this.subscription.add(
|
|
64
|
-
|
|
64
|
+
fromEvent(document, 'mousemove')
|
|
65
65
|
.pipe(takeUntil(mouseup))
|
|
66
66
|
.subscribe((mouseEvent: MouseEvent) => this.onMouseMove(mouseEvent))
|
|
67
67
|
);
|