@swimlane/ngx-datatable 11.1.7 → 11.3.2
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/assets/app.css +5 -6
- package/config/deploy.js +2 -2
- package/config/karma.conf.js +5 -0
- package/config/webpack.dev.js +1 -1
- package/package.json +8 -7
- package/release/assets/app.css +5 -6
- 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-row.component.js +3 -2
- 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 +4 -1
- package/release/components/body/body.component.js +22 -7
- 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.d.ts +1 -0
- package/release/components/body/index.js +1 -0
- package/release/components/body/index.js.map +1 -1
- package/release/components/body/index.metadata.json +1 -1
- package/release/components/body/summary/index.d.ts +1 -0
- package/release/components/body/summary/index.js +7 -0
- package/release/components/body/summary/index.js.map +1 -0
- package/release/components/body/summary/index.metadata.json +1 -0
- package/release/components/body/summary/summary-row.component.d.ts +19 -0
- package/release/components/body/summary/summary-row.component.js +85 -0
- package/release/components/body/summary/summary-row.component.js.map +1 -0
- package/release/components/body/summary/summary-row.component.metadata.json +1 -0
- package/release/components/columns/column.directive.d.ts +2 -0
- package/release/components/columns/column.directive.js +8 -0
- package/release/components/columns/column.directive.js.map +1 -1
- package/release/components/columns/column.directive.metadata.json +1 -1
- package/release/components/datatable.component.css +7 -2
- package/release/components/datatable.component.d.ts +14 -1
- package/release/components/datatable.component.js +34 -7
- package/release/components/datatable.component.js.map +1 -1
- package/release/components/datatable.component.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/datatable.module.js +2 -1
- package/release/datatable.module.js.map +1 -1
- package/release/datatable.module.metadata.json +1 -1
- package/release/directives/resizeable.directive.js +5 -2
- package/release/directives/resizeable.directive.js.map +1 -1
- package/release/events.js +3 -3
- package/release/events.js.map +1 -1
- package/release/events.metadata.json +1 -1
- package/release/index.css +8 -3
- package/release/index.js +201 -42
- package/release/index.min.js +1 -1
- package/release/index.min.js.map +1 -1
- package/release/themes/bootstrap.css +2 -0
- package/release/themes/dark.css +6 -0
- package/release/themes/material.css +6 -0
- package/release/types/table-column.type.d.ts +14 -0
- package/release/utils/column-helper.js +6 -0
- package/release/utils/column-helper.js.map +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/math.js +1 -1
- package/release/utils/math.js.map +1 -1
- package/src/components/body/body-group-header.directive.ts +5 -6
- package/src/components/body/body-row.component.ts +8 -7
- package/src/components/body/body.component.spec.ts +8 -7
- package/src/components/body/body.component.ts +27 -6
- package/src/components/body/index.ts +1 -0
- package/src/components/body/summary/index.ts +1 -0
- package/src/components/body/summary/summary-row.component.spec.ts +131 -0
- package/src/components/body/summary/summary-row.component.ts +74 -0
- package/src/components/columns/column.directive.ts +4 -2
- package/src/components/datatable.component.scss +14 -1
- package/src/components/datatable.component.spec.ts +55 -7
- package/src/components/datatable.component.ts +31 -9
- 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 +8 -6
- package/src/directives/resizeable.directive.ts +4 -2
- package/src/events.ts +3 -3
- package/src/themes/bootstrap.scss +10 -1
- package/src/themes/dark.scss +14 -0
- package/src/themes/material.scss +20 -5
- package/src/types/table-column.type.ts +43 -28
- package/src/utils/column-helper.ts +9 -1
- package/src/utils/column-prop-getters.spec.ts +44 -0
- package/src/utils/column.ts +0 -12
- package/src/utils/math.ts +1 -1
- package/test/index.ts +1 -0
- package/test/jasmine-matchers.d.ts +12 -0
- package/test/jasmine-matchers.ts +70 -0
- package/tslint.json +1 -1
|
@@ -24,13 +24,15 @@ export class DataTableColumnDirective {
|
|
|
24
24
|
@Input() headerCheckboxable: boolean;
|
|
25
25
|
@Input() headerClass: string | ((data: any) => string|any);
|
|
26
26
|
@Input() cellClass: string | ((data: any) => string|any);
|
|
27
|
+
@Input() summaryFunc: (cells: any[]) => any;
|
|
28
|
+
@Input() summaryTemplate: TemplateRef<any>;
|
|
27
29
|
|
|
28
30
|
@Input()
|
|
29
|
-
@ContentChild(DataTableColumnCellDirective, { read: TemplateRef })
|
|
31
|
+
@ContentChild(DataTableColumnCellDirective, { read: TemplateRef })
|
|
30
32
|
cellTemplate: TemplateRef<any>;
|
|
31
33
|
|
|
32
34
|
@Input()
|
|
33
|
-
@ContentChild(DataTableColumnHeaderDirective, { read: TemplateRef })
|
|
35
|
+
@ContentChild(DataTableColumnHeaderDirective, { read: TemplateRef })
|
|
34
36
|
headerTemplate: TemplateRef<any>;
|
|
35
37
|
|
|
36
38
|
}
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
cursor: pointer;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
.resize-handle{
|
|
159
|
+
.resize-handle, .resize-handle--not-resizable {
|
|
160
160
|
display: inline-block;
|
|
161
161
|
position: absolute;
|
|
162
162
|
right: 0;
|
|
@@ -165,6 +165,9 @@
|
|
|
165
165
|
width: 5px;
|
|
166
166
|
padding: 0 4px;
|
|
167
167
|
visibility: hidden;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.resize-handle {
|
|
168
171
|
cursor: ew-resize;
|
|
169
172
|
}
|
|
170
173
|
|
|
@@ -173,6 +176,16 @@
|
|
|
173
176
|
visibility: visible;
|
|
174
177
|
}
|
|
175
178
|
}
|
|
179
|
+
|
|
180
|
+
&:hover {
|
|
181
|
+
.resize-handle--not-resizable {
|
|
182
|
+
visibility: visible;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.datatable-header-cell-template-wrap {
|
|
187
|
+
height: inherit;
|
|
188
|
+
}
|
|
176
189
|
}
|
|
177
190
|
}
|
|
178
191
|
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
} from '.';
|
|
11
11
|
import { NgxDatatableModule } from '../datatable.module';
|
|
12
12
|
|
|
13
|
-
let fixture: ComponentFixture<
|
|
14
|
-
let component:
|
|
13
|
+
let fixture: ComponentFixture<any>;
|
|
14
|
+
let component: any;
|
|
15
15
|
|
|
16
16
|
describe('DatatableComponent', () => {
|
|
17
|
-
beforeEach(async(setupTest));
|
|
17
|
+
beforeEach(async(() => setupTest(TestFixtureComponent)));
|
|
18
18
|
|
|
19
19
|
it('should sort date values', () => {
|
|
20
20
|
const initialRows = [
|
|
@@ -365,27 +365,75 @@ describe('DatatableComponent', () => {
|
|
|
365
365
|
});
|
|
366
366
|
});
|
|
367
367
|
|
|
368
|
+
describe('DatatableComponent With Custom Templates', () => {
|
|
369
|
+
beforeEach(async(() => setupTest(TestFixtureComponentWithCustomTemplates)));
|
|
370
|
+
|
|
371
|
+
it('should sort when the table is initially rendered if `sorts` are provided', () => {
|
|
372
|
+
const initialRows = [
|
|
373
|
+
{ id: 5 },
|
|
374
|
+
{ id: 20 },
|
|
375
|
+
{ id: 12 }
|
|
376
|
+
];
|
|
377
|
+
|
|
378
|
+
const sorts = [
|
|
379
|
+
{
|
|
380
|
+
prop: 'id',
|
|
381
|
+
dir: 'asc'
|
|
382
|
+
}
|
|
383
|
+
];
|
|
384
|
+
|
|
385
|
+
component.rows = initialRows;
|
|
386
|
+
component.sorts = sorts;
|
|
387
|
+
fixture.detectChanges();
|
|
388
|
+
|
|
389
|
+
expect(textContent({ row: 1, column: 1 })).toContain('5', 'Ascending');
|
|
390
|
+
expect(textContent({ row: 2, column: 1 })).toContain('12', 'Ascending');
|
|
391
|
+
expect(textContent({ row: 3, column: 1 })).toContain('20', 'Ascending');
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
|
|
368
395
|
@Component({
|
|
369
396
|
template: `
|
|
370
397
|
<ngx-datatable
|
|
371
398
|
[columns]="columns"
|
|
372
|
-
[rows]="rows"
|
|
399
|
+
[rows]="rows"
|
|
400
|
+
[sorts]="sorts">
|
|
373
401
|
</ngx-datatable>
|
|
374
402
|
`
|
|
375
403
|
})
|
|
376
404
|
class TestFixtureComponent {
|
|
377
405
|
columns: any[] = [];
|
|
378
406
|
rows: any[] = [];
|
|
407
|
+
sorts: any[] = [];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
@Component({
|
|
411
|
+
template: `
|
|
412
|
+
<ngx-datatable [rows]="rows" [sorts]="sorts">
|
|
413
|
+
<ngx-datatable-column name="Id" prop="id">
|
|
414
|
+
<ng-template let-column="column" ngx-datatable-header-template>
|
|
415
|
+
{{ column.name }}
|
|
416
|
+
</ng-template>
|
|
417
|
+
<ng-template let-row="row" ngx-datatable-cell-template>
|
|
418
|
+
{{ row.id }}
|
|
419
|
+
</ng-template>
|
|
420
|
+
</ngx-datatable-column>
|
|
421
|
+
</ngx-datatable>
|
|
422
|
+
`
|
|
423
|
+
})
|
|
424
|
+
class TestFixtureComponentWithCustomTemplates {
|
|
425
|
+
rows: any[] = [];
|
|
426
|
+
sorts: any[] = [];
|
|
379
427
|
}
|
|
380
428
|
|
|
381
|
-
function setupTest() {
|
|
429
|
+
function setupTest(componentClass) {
|
|
382
430
|
return TestBed.configureTestingModule({
|
|
383
|
-
declarations: [
|
|
431
|
+
declarations: [ componentClass ],
|
|
384
432
|
imports: [ NgxDatatableModule ]
|
|
385
433
|
})
|
|
386
434
|
.compileComponents()
|
|
387
435
|
.then(() => {
|
|
388
|
-
fixture = TestBed.createComponent(
|
|
436
|
+
fixture = TestBed.createComponent(componentClass);
|
|
389
437
|
component = fixture.componentInstance;
|
|
390
438
|
});
|
|
391
439
|
}
|
|
@@ -76,6 +76,9 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
|
|
76
76
|
[rowClass]="rowClass"
|
|
77
77
|
[selectCheck]="selectCheck"
|
|
78
78
|
[displayCheck]="displayCheck"
|
|
79
|
+
[summaryRow]="summaryRow"
|
|
80
|
+
[summaryHeight]="summaryHeight"
|
|
81
|
+
[summaryPosition]="summaryPosition"
|
|
79
82
|
(page)="onBodyPage($event)"
|
|
80
83
|
(activate)="activate.emit($event)"
|
|
81
84
|
(rowContextmenu)="onRowContextmenu($event)"
|
|
@@ -118,10 +121,10 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
118
121
|
if (val) {
|
|
119
122
|
this._internalRows = [...val];
|
|
120
123
|
}
|
|
121
|
-
|
|
124
|
+
|
|
122
125
|
// auto sort on new updates
|
|
123
126
|
if (!this.externalSorting) {
|
|
124
|
-
this.
|
|
127
|
+
this.sortInternalRows();
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
// recalculate sizes/etc
|
|
@@ -307,7 +310,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
307
310
|
*
|
|
308
311
|
* - `single`
|
|
309
312
|
* - `multi`
|
|
310
|
-
* - `
|
|
313
|
+
* - `checkbox`
|
|
311
314
|
* - `multiClick`
|
|
312
315
|
* - `cell`
|
|
313
316
|
*
|
|
@@ -428,6 +431,21 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
428
431
|
*/
|
|
429
432
|
@Input() virtualization: boolean = true;
|
|
430
433
|
|
|
434
|
+
/**
|
|
435
|
+
* A flag for switching summary row on / off
|
|
436
|
+
*/
|
|
437
|
+
@Input() summaryRow: boolean = false;
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* A height of summary row
|
|
441
|
+
*/
|
|
442
|
+
@Input() summaryHeight: number = this.rowHeight;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* A property holds a summary row position: top/bottom
|
|
446
|
+
*/
|
|
447
|
+
@Input() summaryPosition: string = 'top';
|
|
448
|
+
|
|
431
449
|
/**
|
|
432
450
|
* Body was scrolled typically in a `scrollbarV:true` scenario.
|
|
433
451
|
*/
|
|
@@ -673,7 +691,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
673
691
|
*/
|
|
674
692
|
ngAfterViewInit(): void {
|
|
675
693
|
if (!this.externalSorting) {
|
|
676
|
-
this.
|
|
694
|
+
this.sortInternalRows();
|
|
677
695
|
}
|
|
678
696
|
|
|
679
697
|
// this has to be done to prevent the change detection
|
|
@@ -681,7 +699,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
681
699
|
if (typeof requestAnimationFrame === 'undefined') {
|
|
682
700
|
return;
|
|
683
701
|
}
|
|
684
|
-
|
|
702
|
+
|
|
685
703
|
requestAnimationFrame(() => {
|
|
686
704
|
this.recalculate();
|
|
687
705
|
|
|
@@ -716,6 +734,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
716
734
|
this._internalColumns = translateTemplates(arr);
|
|
717
735
|
setColumnDefaults(this._internalColumns);
|
|
718
736
|
this.recalculateColumns();
|
|
737
|
+
this.sortInternalRows();
|
|
719
738
|
this.cd.markForCheck();
|
|
720
739
|
}
|
|
721
740
|
}
|
|
@@ -756,7 +775,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
756
775
|
ngDoCheck(): void {
|
|
757
776
|
if (this.rowDiffer.diff(this.rows)) {
|
|
758
777
|
if (!this.externalSorting) {
|
|
759
|
-
this.
|
|
778
|
+
this.sortInternalRows();
|
|
760
779
|
} else {
|
|
761
780
|
this._internalRows = [...this.rows];
|
|
762
781
|
}
|
|
@@ -1012,16 +1031,15 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
1012
1031
|
});
|
|
1013
1032
|
}
|
|
1014
1033
|
|
|
1015
|
-
|
|
1034
|
+
this.sorts = event.sorts;
|
|
1016
1035
|
|
|
1017
1036
|
// this could be optimized better since it will resort
|
|
1018
1037
|
// the rows again on the 'push' detection...
|
|
1019
1038
|
if (this.externalSorting === false) {
|
|
1020
1039
|
// don't use normal setter so we don't resort
|
|
1021
|
-
this.
|
|
1040
|
+
this.sortInternalRows();
|
|
1022
1041
|
}
|
|
1023
1042
|
|
|
1024
|
-
this.sorts = sorts;
|
|
1025
1043
|
// Always go to first page when sorting to see the newly sorted data
|
|
1026
1044
|
this.offset = 0;
|
|
1027
1045
|
this.bodyComponent.updateOffsetY(this.offset);
|
|
@@ -1068,4 +1086,8 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit {
|
|
|
1068
1086
|
onBodySelect(event: any): void {
|
|
1069
1087
|
this.select.emit(event);
|
|
1070
1088
|
}
|
|
1089
|
+
|
|
1090
|
+
private sortInternalRows(): void {
|
|
1091
|
+
this._internalRows = sortRows(this._internalRows, this._internalColumns, this.sorts);
|
|
1092
|
+
}
|
|
1071
1093
|
}
|
|
@@ -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
|
+
}
|