From 027d50eee5f74d661c75551d0703989431e993c5 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Sun, 7 May 2017 21:10:27 -0700 Subject: [PATCH 01/22] feat: Datatable: onclick event for datatable rows closes #468 --- .../core/data-table/data-table.component.html | 2 +- .../data-table/data-table.component.spec.ts | 18 ++++++ .../core/data-table/data-table.component.ts | 60 ++++++++++++------- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index ac272290c8..a478ba6ae8 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -23,7 +23,7 @@ + (click)="clickRow(row); select(row, !isRowSelected(row), $event)"> diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index fb7d15d6dd..4a51dc3f54 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -8,6 +8,7 @@ import 'hammerjs'; import { Component } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TdDataTableComponent, ITdDataTableColumn } from './data-table.component'; +import { TdDataTableRowComponent } from './data-table-row/data-table-row.component'; import { TdDataTableService } from './services/data-table.service'; import { CovalentDataTableModule } from './data-table.module'; import { NgModule, DebugElement } from '@angular/core'; @@ -104,6 +105,23 @@ describe('Component: DataTable', () => { }); })(); }); + + it('should click on a row and see the rowClick Event', + async(inject([], () => { + let fixture: ComponentFixture = TestBed.createComponent(TestFilterColumnComponent); + let component: TestFilterColumnComponent = fixture.debugElement.componentInstance; + + let eventSpy: jasmine.Spy = spyOn(fixture.debugElement.query(By.directive(TdDataTableComponent)).componentInstance, 'clickRow'); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[1].nativeElement.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(eventSpy).toHaveBeenCalled(); + }); + }); + }))); }); @Component({ diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index efd4dc9442..5291685fcd 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -41,6 +41,10 @@ export interface ITdDataTableSelectAllEvent { selected: boolean; } +export interface ITdDataTableClickEvent { + row: any; +} + @Component({ providers: [ TD_DATA_TABLE_CONTROL_VALUE_ACCESSOR ], selector: 'td-data-table', @@ -229,6 +233,13 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI */ @Output('rowSelect') onRowSelect: EventEmitter = new EventEmitter(); + /** + * onRowClick?: function + * Event emitted when a row is clicked. + * Emits an [ITdDataTableClickEvent] implemented object. + */ + @Output('rowClick') onRowClick: EventEmitter = new EventEmitter(); + /** * selectAll?: function * Event emitted when all rows are selected/deselected by the all checkbox. [selectable] needs to be enabled. @@ -319,31 +330,40 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI } /** - * Selects or clears a row depending on 'checked' value + * Selects or clears a row depending on 'checked' value if the row 'isSelectable' */ select(row: any, checked: boolean, event: Event): void { - event.preventDefault(); - // clears all the fields for the dataset - if (!this._multiple) { - this.clearModel(); - } - - if (checked) { - this._value.push(row); - } else { - // if selection is done by a [uniqueId] it uses it to compare, else it compares by reference. - if (this.uniqueId) { - row = this._value.filter((val: any) => { - return val[this.uniqueId] === row[this.uniqueId]; - })[0]; + if (this.isSelectable) { + event.preventDefault(); + // clears all the fields for the dataset + if (!this._multiple) { + this.clearModel(); } - let index: number = this._value.indexOf(row); - if (index > -1) { - this._value.splice(index, 1); + + if (checked) { + this._value.push(row); + } else { + // if selection is done by a [uniqueId] it uses it to compare, else it compares by reference. + if (this.uniqueId) { + row = this._value.filter((val: any) => { + return val[this.uniqueId] === row[this.uniqueId]; + })[0]; + } + let index: number = this._value.indexOf(row); + if (index > -1) { + this._value.splice(index, 1); + } } + this.onRowSelect.emit({row: row, selected: checked}); + this.onChange(this._value); } - this.onRowSelect.emit({row: row, selected: checked}); - this.onChange(this._value); + } + + /** + * emits the onRowClickEvent when a row is clicked + */ + clickRow(row: any): void { + this.onRowClick.emit({row: row}); } /** From a4e4460e53e50524c9403a0b7b8819f446ee2ad4 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Sun, 7 May 2017 21:17:43 -0700 Subject: [PATCH 02/22] changing event name to ITdDataTableRowClickEvent --- src/platform/core/data-table/data-table.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index 5291685fcd..78192b4e11 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -41,7 +41,7 @@ export interface ITdDataTableSelectAllEvent { selected: boolean; } -export interface ITdDataTableClickEvent { +export interface ITdDataTableRowClickEvent { row: any; } @@ -236,9 +236,9 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI /** * onRowClick?: function * Event emitted when a row is clicked. - * Emits an [ITdDataTableClickEvent] implemented object. + * Emits an [ITdDataTableRowClickEvent] implemented object. */ - @Output('rowClick') onRowClick: EventEmitter = new EventEmitter(); + @Output('rowClick') onRowClick: EventEmitter = new EventEmitter(); /** * selectAll?: function From 1828a4ace261a0d63c27550321a164340a17f199 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Sun, 7 May 2017 21:30:58 -0700 Subject: [PATCH 03/22] merging develop into branch --- src/platform/core/data-table/data-table.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index 7ece77c80c..a55b6af648 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -140,8 +140,8 @@ describe('Component: DataTable', () => { it('should click on a row and see the rowClick Event', async(inject([], () => { - let fixture: ComponentFixture = TestBed.createComponent(TestFilterColumnComponent); - let component: TestFilterColumnComponent = fixture.debugElement.componentInstance; + let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicComponent); + let component: TdDataTableBasicComponent = fixture.debugElement.componentInstance; let eventSpy: jasmine.Spy = spyOn(fixture.debugElement.query(By.directive(TdDataTableComponent)).componentInstance, 'clickRow'); From 01c777b47e939fcbb26334612d8e0c03cd4555ed Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Fri, 12 May 2017 09:19:27 -0700 Subject: [PATCH 04/22] update to have selectable row w/ the checkbox, but only if you click the checkbox element and not the entire row --- src/platform/core/data-table/data-table.component.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index cc7aff650c..0b2637cc81 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -25,10 +25,11 @@ + (click)="clickRow(row)"> + [state]="isRowSelected(row) ? 'checked' : 'unchecked'" + (click)="select(row, !isRowSelected(row), $event)"> Date: Fri, 12 May 2017 16:04:29 -0700 Subject: [PATCH 05/22] adding ability to shift multi select rows in datatable --- .../data-table/data-table.component.spec.ts | 14 +-- .../core/data-table/data-table.component.ts | 86 +++++++++++++++---- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index 56d4efef80..c870b0bd64 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -7,10 +7,10 @@ import { import 'hammerjs'; import { Component } from '@angular/core'; import { By } from '@angular/platform-browser'; +import { MdPseudoCheckbox } from '@angular/material'; import { TdDataTableColumnComponent } from './data-table-column/data-table-column.component'; import { TdDataTableRowComponent } from './data-table-row/data-table-row.component'; import { TdDataTableComponent, ITdDataTableColumn } from './data-table.component'; -import { TdDataTableRowComponent } from './data-table-row/data-table-row.component'; import { TdDataTableService } from './services/data-table.service'; import { CovalentDataTableModule } from './data-table.module'; import { NgModule, DebugElement } from '@angular/core'; @@ -170,7 +170,7 @@ describe('Component: DataTable', () => { expect(dataTableComponent.indeterminate).toBeFalsy(); expect(dataTableComponent.allSelected).toBeFalsy(); // select a row with a click event - fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[2].triggerEventHandler('click', new Event('click')); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[2].triggerEventHandler('click', new Event('click')); fixture.detectChanges(); fixture.whenStable().then(() => { // check to see if its in indeterminate state @@ -226,23 +226,23 @@ describe('Component: DataTable', () => { expect(dataTableComponent.indeterminate).toBeFalsy(); expect(dataTableComponent.allSelected).toBeFalsy(); // select a row with a click event - fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[2].triggerEventHandler('click', new Event('click')); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[2].triggerEventHandler('click', new Event('click')); fixture.detectChanges(); fixture.whenStable().then(() => { // check to see if its in indeterminate state expect(dataTableComponent.indeterminate).toBeTruthy(); expect(dataTableComponent.allSelected).toBeFalsy(); // select the rest of the rows - fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[1].triggerEventHandler('click', new Event('click')); - fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[3].triggerEventHandler('click', new Event('click')); - fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[4].triggerEventHandler('click', new Event('click')); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[0].triggerEventHandler('click', new Event('click')); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[1].triggerEventHandler('click', new Event('click')); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[3].triggerEventHandler('click', new Event('click')); fixture.detectChanges(); fixture.whenStable().then(() => { // check to see if its in indeterminate state and allSelected expect(dataTableComponent.indeterminate).toBeTruthy(); expect(dataTableComponent.allSelected).toBeTruthy(); // unselect one of the rows - fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[2].triggerEventHandler('click', new Event('click')); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[2].triggerEventHandler('click', new Event('click')); fixture.detectChanges(); fixture.whenStable().then(() => { // check to see if its in indeterminate state and not allSelected diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index 6936091abf..d36f695c31 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -1,5 +1,5 @@ import { Component, Input, Output, EventEmitter, forwardRef, ChangeDetectionStrategy, ChangeDetectorRef, - ContentChildren, TemplateRef, AfterContentInit, QueryList } from '@angular/core'; + ContentChildren, TemplateRef, AfterContentInit, QueryList, HostListener } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; import { ITdDataTableSortChangeEvent } from './data-table-column/data-table-column.component'; @@ -75,6 +75,9 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI private _sortBy: ITdDataTableColumn; private _sortOrder: TdDataTableSortingOrder = TdDataTableSortingOrder.Ascending; + /** shift select */ + private _lastSelectedIndex: number = -1; + /** template fetching support */ private _templateMap: Map> = new Map>(); @ContentChildren(TdDataTableTemplateDirective) _templates: QueryList; @@ -345,6 +348,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI /** * Selects or clears a row depending on 'checked' value if the row 'isSelectable' + * handles cntrl clicks and shift clicks for multi-select */ select(row: any, checked: boolean, event: Event): void { if (this.isSelectable) { @@ -353,24 +357,48 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI if (!this._multiple) { this.clearModel(); } - - if (checked) { - this._value.push(row); - } else { - // if selection is done by a [uniqueId] it uses it to compare, else it compares by reference. - if (this.uniqueId) { - row = this._value.filter((val: any) => { - return val[this.uniqueId] === row[this.uniqueId]; - })[0]; - } - let index: number = this._value.indexOf(row); - if (index > -1) { - this._value.splice(index, 1); + let currentSelected: number = this._data.findIndex((d: any) => d === row); + this._doSelection(row); + + // Check to see if Shift key is selected and need to select everything in between + let mouseEvent: MouseEvent = event as MouseEvent; + if (this.isMultiple && mouseEvent && mouseEvent.shiftKey && this._lastSelectedIndex > -1) { + let firstSelected: number = this._data.findIndex((d: any) => this.isRowSelected(d)); + let lastSelected: number = this._data.concat([]).reverse().findIndex((d: any) => this.isRowSelected(d)); + // find the index when not reversed + lastSelected = (this._data.length - 1) - lastSelected; + if (firstSelected > -1 && lastSelected > -1) { + for (let i: number = firstSelected; i < lastSelected; i++) { + if (this._data[i] !== row && i !== this._lastSelectedIndex) { + this._doSelection(this._data[i]); + } + } } } - this._calculateCheckboxState(); - this.onRowSelect.emit({row: row, selected: checked}); - this.onChange(this._value); + this._lastSelectedIndex = currentSelected; + } + } + + /** + * Overrides the onselectstart method of the document so other text on the page + * doesn't get selected when doing shift selections. + */ + @HostListener('window:mousedown', ['$event']) + disableOnSelectStart(): void { + if (event.srcElement.tagName === 'MD-PSEUDO-CHECKBOX') { + document.onselectstart = function(): boolean { + return false; + }; + } + } + + /** + * Resets the original onselectstart method. + */ + @HostListener('window:mouseup', ['$event']) + reEnableOnSelectStart(): void { + if (event.srcElement.tagName === 'MD-PSEUDO-CHECKBOX') { + document.onselectstart = undefined; } } @@ -425,6 +453,29 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI } } + /** + * Does the actual Row Selection + */ + private _doSelection(row: any): void { + if (!this.isRowSelected(row)) { + this._value.push(row); + } else { + // if selection is done by a [uniqueId] it uses it to compare, else it compares by reference. + if (this.uniqueId) { + row = this._value.filter((val: any) => { + return val[this.uniqueId] === row[this.uniqueId]; + })[0]; + } + let index: number = this._value.indexOf(row); + if (index > -1) { + this._value.splice(index, 1); + } + } + this._calculateCheckboxState(); + this.onRowSelect.emit({row: row, selected: this.isRowSelected(row)}); + this.onChange(this._value); + } + /** * Calculate all the state of all checkboxes */ @@ -456,5 +507,4 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI } } } - } From 94e81e9b527d402ebc554ac73c8b348bb6570218 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Sat, 13 May 2017 09:49:10 -0700 Subject: [PATCH 06/22] updating demo text to say ability to shift click and adding a unit test that simulate the shift click behavior and tests that is works --- .../data-table/data-table.component.html | 2 +- .../data-table/data-table.component.spec.ts | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/app/components/components/data-table/data-table.component.html b/src/app/components/components/data-table/data-table.component.html index ed91d8e330..a2a1a2d093 100644 --- a/src/app/components/components/data-table/data-table.component.html +++ b/src/app/components/components/data-table/data-table.component.html @@ -354,7 +354,7 @@

No results to display.

Selectable rows - Select multiple rows + Select multiple rows (shift + click for range selection) diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index c870b0bd64..278031bce4 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -256,6 +256,53 @@ describe('Component: DataTable', () => { })(); }); + it('should shift click and select a range of rows', + (done: DoneFn) => { inject([], () => { + let fixture: ComponentFixture = TestBed.createComponent(TdDataTableSelectableTestComponent); + let element: DebugElement = fixture.debugElement; + let component: TdDataTableSelectableTestComponent = fixture.debugElement.componentInstance; + + component.selectable = true; + component.multiple = true; + component.columns = [ + { name: 'sku', label: 'SKU #' }, + { name: 'item', label: 'Item name' }, + { name: 'price', label: 'Price (US$)', numeric: true }, + ]; + + component.data = [{ sku: '1452-2', item: 'Pork Chops', price: 32.11 }, + { sku: '1421-0', item: 'Prime Rib', price: 41.15 }, + { sku: '1452-1', item: 'Sirlone', price: 22.11 }, + { sku: '1421-3', item: 'T-Bone', price: 51.15 }]; + + fixture.detectChanges(); + fixture.whenStable().then(() => { + let dataTableComponent: TdDataTableComponent = fixture.debugElement.query(By.directive(TdDataTableComponent)).componentInstance; + // check how many rows (without counting the columns) were rendered + expect(fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent)).length - 1).toBe(4); + // check to see checkboxes states + expect(dataTableComponent.indeterminate).toBeFalsy(); + expect(dataTableComponent.allSelected).toBeFalsy(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + // select the first and last row with shift key also selected and should then select all checkboxes + let clickEvent: MouseEvent = document.createEvent('MouseEvents'); + // the 12th parameter below 'true' sets the shift key to be clicked at the same time as as the mouse click + clickEvent.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, true/*shiftkey*/, false, 0, document.body.parentNode); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[0].nativeElement.dispatchEvent(clickEvent); + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[3].nativeElement.dispatchEvent(clickEvent); + fixture.detectChanges(); + fixture.whenStable().then(() => { + // check to see if allSelected is true + expect(dataTableComponent.allSelected).toBeTruthy(); + done(); + }); + }); + }); + })(); + }); + it('should click on a row and see the rowClick Event', async(inject([], () => { let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicComponent); From 8f9a666be661d3cecc128385a1ad9a727501aeca Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 14 May 2017 19:02:19 -0700 Subject: [PATCH 07/22] chore(): expose ITdDataTableRowClickEvent in the API --- src/platform/core/data-table/data-table.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/core/data-table/data-table.module.ts b/src/platform/core/data-table/data-table.module.ts index 532e5d9e40..6897c24a14 100644 --- a/src/platform/core/data-table/data-table.module.ts +++ b/src/platform/core/data-table/data-table.module.ts @@ -21,7 +21,7 @@ const TD_DATA_TABLE: Type[] = [ TdDataTableTableComponent, ]; -export { TdDataTableComponent, TdDataTableSortingOrder, +export { TdDataTableComponent, TdDataTableSortingOrder, ITdDataTableRowClickEvent, ITdDataTableColumn, ITdDataTableSelectEvent, ITdDataTableSelectAllEvent } from './data-table.component'; export { TdDataTableService } from './services/data-table.service'; export { TdDataTableColumnComponent, From 365edfde2f901f313d873a1fc013a33904343f41 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 14 May 2017 19:04:07 -0700 Subject: [PATCH 08/22] feat(): use DOCUMENT if its there, else dont use it also point the text selection events directly into the md-pseudo-checkbox instead of the host component and comparing the tagName --- .../core/data-table/data-table.component.html | 4 +++- .../core/data-table/data-table.component.ts | 24 +++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index 0b2637cc81..96859ac560 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -25,10 +25,12 @@ + (click)="handleRowClick(row)"> diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index d36f695c31..80c4e532df 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -1,5 +1,6 @@ import { Component, Input, Output, EventEmitter, forwardRef, ChangeDetectionStrategy, ChangeDetectorRef, - ContentChildren, TemplateRef, AfterContentInit, QueryList, HostListener } from '@angular/core'; + ContentChildren, TemplateRef, AfterContentInit, QueryList, Inject, Optional } from '@angular/core'; +import { DOCUMENT } from '@angular/platform-browser'; import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; import { ITdDataTableSortChangeEvent } from './data-table-column/data-table-column.component'; @@ -269,7 +270,8 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI @Output('selectAll') onSelectAll: EventEmitter = new EventEmitter(); - constructor(private _changeDetectorRef: ChangeDetectorRef) {} + constructor(@Optional() @Inject(DOCUMENT) private _document: any, + private _changeDetectorRef: ChangeDetectorRef) {} /** * Loads templates and sets them in a map for faster access. @@ -383,11 +385,10 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI * Overrides the onselectstart method of the document so other text on the page * doesn't get selected when doing shift selections. */ - @HostListener('window:mousedown', ['$event']) - disableOnSelectStart(): void { - if (event.srcElement.tagName === 'MD-PSEUDO-CHECKBOX') { - document.onselectstart = function(): boolean { - return false; + disableTextSelection(): void { + if (this._document) { + this._document.onselectstart = function(): boolean { + return false; }; } } @@ -395,17 +396,16 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI /** * Resets the original onselectstart method. */ - @HostListener('window:mouseup', ['$event']) - reEnableOnSelectStart(): void { - if (event.srcElement.tagName === 'MD-PSEUDO-CHECKBOX') { - document.onselectstart = undefined; + enableTextSelection(): void { + if (this._document) { + this._document.onselectstart = undefined; } } /** * emits the onRowClickEvent when a row is clicked */ - clickRow(row: any): void { + handleRowClick(row: any): void { this.onRowClick.emit({row: row}); } From 5409ae9aa4f8c56d6d4cbfd0d3289b29bab44ced Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 14 May 2017 19:06:05 -0700 Subject: [PATCH 09/22] chore(): add (rowClick) in data-table docs --- .../components/components/data-table/data-table.component.ts | 5 +++++ src/platform/core/data-table/data-table.component.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/components/components/data-table/data-table.component.ts b/src/app/components/components/data-table/data-table.component.ts index 2802a661a7..f47a45c31f 100644 --- a/src/app/components/components/data-table/data-table.component.ts +++ b/src/app/components/components/data-table/data-table.component.ts @@ -66,6 +66,11 @@ export class DataTableDemoComponent implements OnInit { Emits an [ITdDataTableSelectAllEvent] implemented object.`, name: 'selectAll', type: `function()`, + }, { + description: `Event emitted when a row is clicked. + Emits an [ITdDataTableRowClickEvent] implemented object.`, + name: 'rowClick', + type: `function()`, }, { description: `Refreshes data table and updates [data] and [columns]`, name: 'refresh', diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index 80c4e532df..59bf992a37 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -256,7 +256,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI @Output('rowSelect') onRowSelect: EventEmitter = new EventEmitter(); /** - * onRowClick?: function + * rowClick?: function * Event emitted when a row is clicked. * Emits an [ITdDataTableRowClickEvent] implemented object. */ From 1ebdd62c7abeb5f77d0611971251dda16e9b8549 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 14 May 2017 19:12:57 -0700 Subject: [PATCH 10/22] chore(data-table): remove checked arg in select method removing it since its not needed anymore in the select method, it wasnt being used. --- src/platform/core/data-table/data-table.component.html | 2 +- src/platform/core/data-table/data-table.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index 96859ac560..31bb38595b 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -31,7 +31,7 @@ [state]="isRowSelected(row) ? 'checked' : 'unchecked'" (mousedown)="disableTextSelection()" (mouseup)="enableTextSelection()" - (click)="select(row, !isRowSelected(row), $event)"> + (click)="select(row, $event)">
Date: Sun, 14 May 2017 19:42:40 -0700 Subject: [PATCH 11/22] chore(data-table): test the click event as output --- .../data-table/data-table.component.spec.ts | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index 278031bce4..4f7f4467d6 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -26,8 +26,9 @@ describe('Component: DataTable', () => { CovalentDataTableModule, ], declarations: [ - TdDataTableBasicComponent, + TdDataTableBasicTestComponent, TdDataTableSelectableTestComponent, + TdDataTableRowClickTestComponent, ], providers: [ TdDataTableService, @@ -38,8 +39,8 @@ describe('Component: DataTable', () => { it('should set hidden and not get search hits and set it to false and get search results', (done: DoneFn) => { inject([TdDataTableService], (tdDataTableService: TdDataTableService) => { - let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicComponent); - let component: TdDataTableBasicComponent = fixture.debugElement.componentInstance; + let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicTestComponent); + let component: TdDataTableBasicTestComponent = fixture.debugElement.componentInstance; component.columns[1].hidden = false; // backwards compatability test @@ -86,8 +87,8 @@ describe('Component: DataTable', () => { it('should set filter and not get search hits and set it to false and get search results', (done: DoneFn) => { inject([TdDataTableService], (tdDataTableService: TdDataTableService) => { - let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicComponent); - let component: TdDataTableBasicComponent = fixture.debugElement.componentInstance; + let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicTestComponent); + let component: TdDataTableBasicTestComponent = fixture.debugElement.componentInstance; component.columns[1].filter = false; @@ -305,17 +306,17 @@ describe('Component: DataTable', () => { it('should click on a row and see the rowClick Event', async(inject([], () => { - let fixture: ComponentFixture = TestBed.createComponent(TdDataTableBasicComponent); - let component: TdDataTableBasicComponent = fixture.debugElement.componentInstance; + let fixture: ComponentFixture = TestBed.createComponent(TdDataTableRowClickTestComponent); + let component: TdDataTableRowClickTestComponent = fixture.debugElement.componentInstance; - let eventSpy: jasmine.Spy = spyOn(fixture.debugElement.query(By.directive(TdDataTableComponent)).componentInstance, 'clickRow'); + let eventSpy: jasmine.Spy = spyOn(component, 'clickEvent'); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[1].nativeElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(eventSpy).toHaveBeenCalled(); + expect(eventSpy.calls.count()).toBe(1); }); }); }))); @@ -329,7 +330,7 @@ describe('Component: DataTable', () => { [columns]="columns"> `, }) -class TdDataTableBasicComponent { +class TdDataTableBasicTestComponent { data: any[] = [ { sku: '1452-2', item: 'Pork Chops', price: 32.11 }, { sku: '1421-0', item: 'Prime Rib', price: 41.15 }, @@ -356,3 +357,26 @@ class TdDataTableSelectableTestComponent { selectable: boolean = false; multiple: boolean = false; } + +@Component({ + template: ` + + `, +}) +class TdDataTableRowClickTestComponent { + data: any[] = [ + { sku: '1452-2', item: 'Pork Chops', price: 32.11 }, + { sku: '1421-0', item: 'Prime Rib', price: 41.15 }, + ]; + columns: ITdDataTableColumn[] = [ + { name: 'sku', label: 'SKU #' }, + { name: 'item', label: 'Item name' }, + { name: 'price', label: 'Price (US$)', numeric: true }, + ]; + clickEvent(): void { + /* noop */ + } +} From 1281a515139b9b4b7b5ad40f898dceaae2d4e2c2 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 14 May 2017 19:55:00 -0700 Subject: [PATCH 12/22] feat(data-table): adding keyboard a11y for selections --- src/platform/core/data-table/_data-table-theme.scss | 1 + src/platform/core/data-table/data-table.component.html | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platform/core/data-table/_data-table-theme.scss b/src/platform/core/data-table/_data-table-theme.scss index 91159dfa6a..40c078542f 100644 --- a/src/platform/core/data-table/_data-table-theme.scss +++ b/src/platform/core/data-table/_data-table-theme.scss @@ -46,6 +46,7 @@ } } &.mat-selectable tbody > tr.td-data-table-row { + &:not([disabled]):focus, &:not([disabled]):hover { background-color: mat-color($background, 'hover'); } diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index 31bb38595b..4492676fcd 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -8,7 +8,8 @@ [disabled]="!hasData" [indeterminate]="indeterminate && !allSelected && hasData" [checked]="allSelected && hasData" - (click)="selectAll(!checkBoxAll.checked)"> + (click)="selectAll(!checkBoxAll.checked)" + (keyup.enter)="selectAll(!checkBoxAll.checked)"> {{column.label}} + (click)="handleRowClick(row)" + (keyup.enter)="select(row, $event)"> Date: Sun, 14 May 2017 20:33:49 -0700 Subject: [PATCH 13/22] feat(data-table): add more keyboard a11y added space press to select all checkbox also added support for enter/space/up/down on data table rows --- .../data-table-row.component.ts | 4 ++ .../core/data-table/data-table.component.html | 11 ++-- .../core/data-table/data-table.component.ts | 64 +++++++++++++++++-- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/platform/core/data-table/data-table-row/data-table-row.component.ts b/src/platform/core/data-table/data-table-row/data-table-row.component.ts index 72b48701ff..7d003fb05a 100644 --- a/src/platform/core/data-table/data-table-row/data-table-row.component.ts +++ b/src/platform/core/data-table/data-table-row/data-table-row.component.ts @@ -11,5 +11,9 @@ export class TdDataTableRowComponent { constructor(private _elementRef: ElementRef, private _renderer: Renderer2) { this._renderer.addClass(this._elementRef.nativeElement, 'td-data-table-row'); } + + focus(): void { + this._elementRef.nativeElement.focus(); + } } diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index 4492676fcd..650352681a 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -9,7 +9,9 @@ [indeterminate]="indeterminate && !allSelected && hasData" [checked]="allSelected && hasData" (click)="selectAll(!checkBoxAll.checked)" - (keyup.enter)="selectAll(!checkBoxAll.checked)"> + (keyup.enter)="selectAll(!checkBoxAll.checked)" + (keyup.space)="selectAll(!checkBoxAll.checked)" + (keydown.space)="blockEvent($event)"> + (keyup)="_rowKeyup($event, row, rowIndex)" + (keydown.space)="blockEvent($event)"> + (click)="select(row, $event, rowIndex)"> > = new Map>(); @ContentChildren(TdDataTableTemplateDirective) _templates: QueryList; + @ViewChildren(TdDataTableRowComponent) _rows: QueryList; + /** * Returns true if all values are selected. */ @@ -352,14 +357,13 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI * Selects or clears a row depending on 'checked' value if the row 'isSelectable' * handles cntrl clicks and shift clicks for multi-select */ - select(row: any, event: Event): void { + select(row: any, event: Event, currentSelected: number): void { if (this.isSelectable) { - event.preventDefault(); + this.blockEvent(event); // clears all the fields for the dataset if (!this._multiple) { this.clearModel(); } - let currentSelected: number = this._data.findIndex((d: any) => d === row); this._doSelection(row); // Check to see if Shift key is selected and need to select everything in between @@ -423,6 +427,58 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI this.onSortChange.next({ name: this._sortBy.name, order: this._sortOrder }); } + /** + * Handle all keyup events when focusing a data table row + */ + _rowKeyup(event: KeyboardEvent, row: any, index: number): void { + let length: number; + let rows: TdDataTableRowComponent[]; + switch (event.keyCode) { + case ENTER: + case SPACE: + /** if user presses enter or space, the row should be selected */ + this.select(row, event, index); + break; + case UP_ARROW: + rows = this._rows.toArray(); + length = rows.length; + /** + * if users presses the up arrow, we focus the prev row + * unless its the first row, then we move to the last row + */ + if (index === 0) { + rows[length - 1].focus(); + } else { + rows[index - 1].focus(); + } + this.blockEvent(event); + break; + case DOWN_ARROW: + rows = this._rows.toArray(); + length = rows.length; + /** + * if users presses the down arrow, we focus the next row + * unless its the last row, then we move to the first row + */ + if (index === (length - 1)) { + rows[0].focus(); + } else { + rows[index + 1].focus(); + } + this.blockEvent(event); + break; + default: + // default + } + } + + /** + * Method to prevent the default events + */ + blockEvent(event: Event): void { + event.preventDefault(); + } + /** * Implemented as part of ControlValueAccessor. */ From 11173428199666652913f0d92e77922fd9438f8f Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Sun, 14 May 2017 21:53:37 -0700 Subject: [PATCH 14/22] chore(): simplify shift selection to use index before it was finding the selected rows, but as a user i would expect to always toggle from first index to last index also its better to simplify it for performance issues, since with lots of rows this couldve take a toll --- .../core/data-table/data-table.component.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index cbbf8d0359..23921587c5 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -369,16 +369,14 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI // Check to see if Shift key is selected and need to select everything in between let mouseEvent: MouseEvent = event as MouseEvent; if (this.isMultiple && mouseEvent && mouseEvent.shiftKey && this._lastSelectedIndex > -1) { - let firstSelected: number = this._data.findIndex((d: any) => this.isRowSelected(d)); - let lastSelected: number = this._data.concat([]).reverse().findIndex((d: any) => this.isRowSelected(d)); - // find the index when not reversed - lastSelected = (this._data.length - 1) - lastSelected; - if (firstSelected > -1 && lastSelected > -1) { - for (let i: number = firstSelected; i < lastSelected; i++) { - if (this._data[i] !== row && i !== this._lastSelectedIndex) { - this._doSelection(this._data[i]); - } - } + let firstIndex: number = currentSelected; + let lastIndex: number = this._lastSelectedIndex; + if (currentSelected > this._lastSelectedIndex) { + firstIndex = this._lastSelectedIndex; + lastIndex = currentSelected; + } + for (let i: number = firstIndex + 1; i < lastIndex; i++) { + this._doSelection(this._data[i]); } } this._lastSelectedIndex = currentSelected; From 565ec7fff75e026e8a0f1e6fcd18bbc0a827ad98 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Mon, 15 May 2017 10:25:59 -0700 Subject: [PATCH 15/22] Fixing case where selecting a row, then unselecting the row and then doing shift click. Also fixing case where selecting a row and then unselecting everything --- .../core/data-table/data-table.component.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index 23921587c5..a9acb43fd1 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -81,6 +81,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI /** shift select */ private _lastSelectedIndex: number = -1; + private _selectedBeforeLastIndex: number = -1; /** template fetching support */ private _templateMap: Map> = new Map>(); @@ -379,7 +380,17 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI this._doSelection(this._data[i]); } } - this._lastSelectedIndex = currentSelected; + // set the last selected attribute unless the last selected unchecked a row + if (this.isRowSelected(this._data[currentSelected])) { + this._selectedBeforeLastIndex = this._lastSelectedIndex; + this._lastSelectedIndex = currentSelected; + } else { + this._lastSelectedIndex = this._selectedBeforeLastIndex; + } + // everything is unselected so start over + if (!this._indeterminate && !this._allSelected) { + this._lastSelectedIndex = -1; + } } } From 15a1a2638515e6868cd3ac29b52d149692973496 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Mon, 15 May 2017 13:01:07 -0700 Subject: [PATCH 16/22] Ability for Holding Shift Key and moving up and down the datatable with arrow keys only, no mouse --- .../core/data-table/data-table.component.html | 3 +- .../core/data-table/data-table.component.ts | 34 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index 650352681a..f287f2b520 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -31,7 +31,8 @@ *ngFor="let row of data; let rowIndex = index" (click)="handleRowClick(row)" (keyup)="_rowKeyup($event, row, rowIndex)" - (keydown.space)="blockEvent($event)"> + (keydown.space)="blockEvent($event)" + (keydown.shift.space)="blockEvent($event)"> 'ASC', + Descending = 'DESC', +} + @Component({ providers: [ TD_DATA_TABLE_CONTROL_VALUE_ACCESSOR ], selector: 'td-data-table', @@ -82,6 +87,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI /** shift select */ private _lastSelectedIndex: number = -1; private _selectedBeforeLastIndex: number = -1; + private _lastArrowKeyDirection: TdDataTableArrowKeyDirection; /** template fetching support */ private _templateMap: Map> = new Map>(); @@ -451,30 +457,54 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI case UP_ARROW: rows = this._rows.toArray(); length = rows.length; + + // check to see if changing direction and need to toggle the current row + if (this._lastArrowKeyDirection === TdDataTableArrowKeyDirection.Descending) { + index++; + } /** * if users presses the up arrow, we focus the prev row * unless its the first row, then we move to the last row */ if (index === 0) { - rows[length - 1].focus(); + if (!event.shiftKey) { + rows[length - 1].focus(); + } } else { rows[index - 1].focus(); } this.blockEvent(event); + if (event.shiftKey) { + this._doSelection(this._data[index - 1]); + // if the checkboxes are all unselected then start over otherwise handle changing direction + this._lastArrowKeyDirection = (!this._allSelected && !this._indeterminate) ? undefined : TdDataTableArrowKeyDirection.Ascending; + } break; case DOWN_ARROW: rows = this._rows.toArray(); length = rows.length; + + // check to see if changing direction and need to toggle the current row + if (this._lastArrowKeyDirection === TdDataTableArrowKeyDirection.Ascending) { + index--; + } /** * if users presses the down arrow, we focus the next row * unless its the last row, then we move to the first row */ if (index === (length - 1)) { - rows[0].focus(); + if (!event.shiftKey) { + rows[0].focus(); + } } else { rows[index + 1].focus(); } this.blockEvent(event); + if (event.shiftKey) { + this._doSelection(this._data[index + 1]); + // if the checkboxes are all unselected then start over otherwise handle changing direction + this._lastArrowKeyDirection = (!this._allSelected && !this._indeterminate) ? undefined : TdDataTableArrowKeyDirection.Descending; + } break; default: // default From b9a0a45e0cc774edf8873cdbe3d347c1291f5b95 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Mon, 15 May 2017 19:42:25 -0700 Subject: [PATCH 17/22] clickable input to datatable allows for rowClick event to be fired. If set to false the event isn't fired. --- .../data-table/data-table.component.html | 14 ++++++++--- .../data-table/data-table.component.ts | 11 ++++++++- .../core/data-table/_data-table-theme.scss | 13 +++++++++-- .../core/data-table/data-table.component.html | 13 +++++++---- .../core/data-table/data-table.component.ts | 23 ++++++++++++++++--- 5 files changed, 60 insertions(+), 14 deletions(-) diff --git a/src/app/components/components/data-table/data-table.component.html b/src/app/components/components/data-table/data-table.component.html index a2a1a2d093..9b1d7c1d64 100644 --- a/src/app/components/components/data-table/data-table.component.html +++ b/src/app/components/components/data-table/data-table.component.html @@ -224,12 +224,14 @@

Paging Bar / Search Box / Sortable components

[data]="filteredData" [columns]="columns" [selectable]="selectable" + [clickable]="clickable" [multiple]="multiple" [sortable]="true" [sortBy]="sortBy" [(ngModel)]="selectedRows" [sortOrder]="sortOrder" - (sortChange)="sort($event)"> + (sortChange)="sort($event)" + (rowClick)="showAlert($event)">

No results to display.

@@ -260,6 +262,9 @@

No results to display.

#dataTable [data]="filteredData" [columns]="columns" + [selectable]="selectable" + [clickable]="clickable" + [multiple]="multiple" [sortable]="true" [sortBy]="sortBy" [sortOrder]="sortOrder" @@ -353,8 +358,11 @@

No results to display.

Selectable rows - - Select multiple rows (shift + click for range selection) + + Clickable rows + + + Multiple rows (shift + click for range selection)
diff --git a/src/app/components/components/data-table/data-table.component.ts b/src/app/components/components/data-table/data-table.component.ts index f47a45c31f..fc4c6f01e3 100644 --- a/src/app/components/components/data-table/data-table.component.ts +++ b/src/app/components/components/data-table/data-table.component.ts @@ -30,9 +30,13 @@ export class DataTableDemoComponent implements OnInit { name: 'columns?', type: 'ITdDataTableColumn[]', }, { - description: `Enables row selection events, hover and selected row states.`, + description: `Enables row selection, click events and selected row state.`, name: 'selectable?', type: 'boolean', + }, { + description: `Enables row click events and hover row state.`, + name: 'clickable?', + type: 'boolean', }, { description: `Enables multiple row selection. [selectable] needs to be enabled.`, name: 'multiple?', @@ -272,6 +276,7 @@ export class DataTableDemoComponent implements OnInit { ]; basicData: any[] = this.data.slice(0, 4); selectable: boolean = true; + clickable: boolean = false; multiple: boolean = true; filterColumn: boolean = true; @@ -345,4 +350,8 @@ export class DataTableDemoComponent implements OnInit { this.columns.forEach((c: any) => c.tooltip = `This is ${c.label}!`); } } + + showAlert(event: any): void { + alert('You clicked on row: ' + event.row.name); + } } diff --git a/src/platform/core/data-table/_data-table-theme.scss b/src/platform/core/data-table/_data-table-theme.scss index 40c078542f..3e9a2015fd 100644 --- a/src/platform/core/data-table/_data-table-theme.scss +++ b/src/platform/core/data-table/_data-table-theme.scss @@ -46,14 +46,23 @@ } } &.mat-selectable tbody > tr.td-data-table-row { - &:not([disabled]):focus, - &:not([disabled]):hover { + &:not([disabled]):not(.mat-selected):focus { background-color: mat-color($background, 'hover'); } &.mat-selected { background-color: mat-color($accent, 0.12); } } + &.mat-clickable tbody > tr.td-data-table-row { + &:not([disabled]){ + &:hover { + background-color: mat-color($background, 'hover'); + } + &:active { + background-color: mat-color($accent, 0.12); + } + } + } } .mat-selected-title { background-color: mat-color($accent, 0.12); diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index f287f2b520..bb3fac4592 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -1,6 +1,7 @@
+ [class.mat-selectable]="isSelectable" + [class.mat-clickable]="isClickable"> + (keydown.shift.space)="blockEvent($event)" + (keydown.shift)="disableTextSelection()" + (keyup.shift)="enableTextSelection()"> Date: Mon, 15 May 2017 20:31:00 -0700 Subject: [PATCH 20/22] fix for when multiple is false and only allowing 1 selection and fix for being able to deselect current selection when multiple is false --- src/platform/core/data-table/data-table.component.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index cfeb81ed9e..38fd47f78c 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -379,12 +379,8 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI * handles cntrl clicks and shift clicks for multi-select */ select(row: any, event: Event, currentSelected: number): void { - if (this.isSelectable || this.isClickable) { + if (this.isSelectable) { this.blockEvent(event); - // clears all the fields for the dataset - if (!this._multiple) { - this.clearModel(); - } this._doSelection(row); // Check to see if Shift key is selected and need to select everything in between @@ -491,7 +487,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI rows[index - 1].focus(); } this.blockEvent(event); - if (event.shiftKey) { + if (this.isMultiple && event.shiftKey) { this._doSelection(this._data[index - 1]); // if the checkboxes are all unselected then start over otherwise handle changing direction this._lastArrowKeyDirection = (!this._allSelected && !this._indeterminate) ? undefined : TdDataTableArrowKeyDirection.Ascending; @@ -517,7 +513,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI rows[index + 1].focus(); } this.blockEvent(event); - if (event.shiftKey) { + if (this.isMultiple && event.shiftKey) { this._doSelection(this._data[index + 1]); // if the checkboxes are all unselected then start over otherwise handle changing direction this._lastArrowKeyDirection = (!this._allSelected && !this._indeterminate) ? undefined : TdDataTableArrowKeyDirection.Descending; @@ -569,6 +565,7 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI * Does the actual Row Selection */ private _doSelection(row: any): void { + console.log(this.isRowSelected(row)); if (!this.isRowSelected(row)) { this._value.push(row); } else { From 7cfa95b4b864302d0ae10e506fb39e5d464347e9 Mon Sep 17 00:00:00 2001 From: "jeremy.smartt" Date: Mon, 15 May 2017 20:35:43 -0700 Subject: [PATCH 21/22] fix unit tests --- .../core/data-table/data-table.component.spec.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index 4f7f4467d6..2adbf1782e 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -316,7 +316,17 @@ describe('Component: DataTable', () => { fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[1].nativeElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(eventSpy.calls.count()).toBe(1); + expect(eventSpy.calls.count()).toBe(0); + + component.clickable = true; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[1].nativeElement.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(eventSpy.calls.count()).toBe(1); + }); + }); }); }); }))); @@ -363,6 +373,7 @@ class TdDataTableSelectableTestComponent { `, }) @@ -376,6 +387,7 @@ class TdDataTableRowClickTestComponent { { name: 'item', label: 'Item name' }, { name: 'price', label: 'Price (US$)', numeric: true }, ]; + clickable: boolean = false; clickEvent(): void { /* noop */ } From 411af75ffa7a2b6206ea513e1e24c5c945b594ef Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Mon, 15 May 2017 20:36:23 -0700 Subject: [PATCH 22/22] chore(): fixed single selection we need to check the prev state when its single selection --- src/platform/core/data-table/data-table.component.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index 38fd47f78c..4598af0d2b 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -565,8 +565,11 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI * Does the actual Row Selection */ private _doSelection(row: any): void { - console.log(this.isRowSelected(row)); - if (!this.isRowSelected(row)) { + let wasSelected: boolean = this.isRowSelected(row); + if (!this._multiple) { + this.clearModel(); + } + if (!wasSelected) { this._value.push(row); } else { // if selection is done by a [uniqueId] it uses it to compare, else it compares by reference.
{{column.label}}
Date: Mon, 15 May 2017 20:03:52 -0700 Subject: [PATCH 18/22] chore(): use dialog instead of alert --- .../components/components/data-table/data-table.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/components/components/data-table/data-table.component.ts b/src/app/components/components/data-table/data-table.component.ts index fc4c6f01e3..baf5e89feb 100644 --- a/src/app/components/components/data-table/data-table.component.ts +++ b/src/app/components/components/data-table/data-table.component.ts @@ -352,6 +352,8 @@ export class DataTableDemoComponent implements OnInit { } showAlert(event: any): void { - alert('You clicked on row: ' + event.row.name); + this._dialogService.openAlert({ + message: 'You clicked on row: ' + event.row.name, + }); } } From 980cbbfbb1e5299e349dfb523e322ffb2e6e3459 Mon Sep 17 00:00:00 2001 From: emoralesb05 Date: Mon, 15 May 2017 20:08:16 -0700 Subject: [PATCH 19/22] fix(): be able to tab when its `selectable` --- src/platform/core/data-table/data-table.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index bb3fac4592..fca74c66fd 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -27,11 +27,11 @@ {{column.label}}