Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(data-table): onclick event for datatable rows, select event only on checkboxes, multi shift click and basic a11y (closes #468) (closes #592) #572

Merged
merged 31 commits into from
May 16, 2017
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
027d50e
feat: Datatable: onclick event for datatable rows
May 8, 2017
a4e4460
changing event name to ITdDataTableRowClickEvent
May 8, 2017
cf2d51a
Merge branch 'develop' into feature/datatable-row-onclick
jeremysmartt May 8, 2017
1828a4a
merging develop into branch
May 8, 2017
eec687e
Merge branch 'develop' into feature/datatable-row-onclick
jeremysmartt May 8, 2017
632453d
Merge branch 'develop' into feature/datatable-row-onclick
May 12, 2017
01c777b
update to have selectable row w/ the checkbox, but only if you click …
May 12, 2017
c28d148
adding ability to shift multi select rows in datatable
May 12, 2017
94e81e9
updating demo text to say ability to shift click and adding a unit te…
May 13, 2017
35b1eb3
Merge branch 'develop' into feature/datatable-row-onclick
emoralesb05 May 15, 2017
3a09de4
Merge branch 'develop' into feature/datatable-row-onclick
emoralesb05 May 15, 2017
8f9a666
chore(): expose ITdDataTableRowClickEvent in the API
emoralesb05 May 15, 2017
365edfd
feat(): use DOCUMENT if its there, else dont use it
emoralesb05 May 15, 2017
5409ae9
chore(): add (rowClick) in data-table docs
emoralesb05 May 15, 2017
1ebdd62
chore(data-table): remove checked arg in select method
emoralesb05 May 15, 2017
cb189ee
Merge branch 'develop' into feature/datatable-row-onclick
kyleledbetter May 15, 2017
ec038aa
chore(data-table): test the click event as output
emoralesb05 May 15, 2017
1281a51
feat(data-table): adding keyboard a11y for selections
emoralesb05 May 15, 2017
dd389f1
feat(data-table): add more keyboard a11y
emoralesb05 May 15, 2017
f453f6e
Merge branch 'develop' into feature/datatable-row-onclick
emoralesb05 May 15, 2017
1117342
chore(): simplify shift selection to use index
emoralesb05 May 15, 2017
565ec7f
Fixing case where selecting a row, then unselecting the row and then …
May 15, 2017
15a1a26
Ability for Holding Shift Key and moving up and down the datatable wi…
May 15, 2017
b9a0a45
clickable input to datatable allows for rowClick event to be fired. …
May 16, 2017
cbd2116
chore(): use dialog instead of alert
emoralesb05 May 16, 2017
980cbbf
fix(): be able to tab when its `selectable`
emoralesb05 May 16, 2017
b1bbc98
fix for when multiple is false and only allowing 1 selection and fix …
May 16, 2017
7cfa95b
fix unit tests
May 16, 2017
411af75
chore(): fixed single selection
emoralesb05 May 16, 2017
9bd4f9c
Merge branch 'feature/datatable-row-onclick' of https://github.com/Te…
emoralesb05 May 16, 2017
5fc7731
Merge branch 'develop' into feature/datatable-row-onclick
emoralesb05 May 16, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ <h3>No results to display.</h3>
Selectable rows
</md-slide-toggle>
<md-slide-toggle class="push-left" color="accent" [(ngModel)]="multiple" [disabled]="!selectable">
Select multiple rows
Select multiple rows (shift + click for range selection)
</md-slide-toggle>
</div>
<md-divider></md-divider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions src/platform/core/data-table/_data-table-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
}
}
&.mat-selectable tbody > tr.td-data-table-row {
&:not([disabled]):focus,
&:not([disabled]):hover {
background-color: mat-color($background, 'hover');
}
Expand Down
12 changes: 9 additions & 3 deletions src/platform/core/data-table/data-table.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -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)">
</md-checkbox>
</th>
<th td-data-table-column
Expand All @@ -23,12 +24,17 @@
<span [mdTooltip]="column.tooltip">{{column.label}}</span>
</th>
<tr td-data-table-row
[tabIndex]="isSelectable ? 0 : -1"
[class.mat-selected]="isSelectable && isRowSelected(row)"
*ngFor="let row of data"
(click)="isSelectable && select(row, !isRowSelected(row), $event)">
(click)="handleRowClick(row)"
(keyup.enter)="select(row, $event)">
<td td-data-table-cell class="mat-checkbox-cell" *ngIf="isSelectable">
<md-pseudo-checkbox
[state]="isRowSelected(row) ? 'checked' : 'unchecked'">
[state]="isRowSelected(row) ? 'checked' : 'unchecked'"
(mousedown)="disableTextSelection()"
(mouseup)="enableTextSelection()"
(click)="select(row, $event)">
</md-pseudo-checkbox>
</td>
<td td-data-table-cell
Expand Down
113 changes: 100 additions & 13 deletions src/platform/core/data-table/data-table.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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';
Expand All @@ -25,8 +26,9 @@ describe('Component: DataTable', () => {
CovalentDataTableModule,
],
declarations: [
TdDataTableBasicComponent,
TdDataTableBasicTestComponent,
TdDataTableSelectableTestComponent,
TdDataTableRowClickTestComponent,
],
providers: [
TdDataTableService,
Expand All @@ -37,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<any> = TestBed.createComponent(TdDataTableBasicComponent);
let component: TdDataTableBasicComponent = fixture.debugElement.componentInstance;
let fixture: ComponentFixture<any> = TestBed.createComponent(TdDataTableBasicTestComponent);
let component: TdDataTableBasicTestComponent = fixture.debugElement.componentInstance;

component.columns[1].hidden = false;
// backwards compatability test
Expand Down Expand Up @@ -85,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<any> = TestBed.createComponent(TdDataTableBasicComponent);
let component: TdDataTableBasicComponent = fixture.debugElement.componentInstance;
let fixture: ComponentFixture<any> = TestBed.createComponent(TdDataTableBasicTestComponent);
let component: TdDataTableBasicTestComponent = fixture.debugElement.componentInstance;

component.columns[1].filter = false;

Expand Down Expand Up @@ -169,7 +171,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
Expand Down Expand Up @@ -225,23 +227,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
Expand All @@ -255,8 +257,70 @@ describe('Component: DataTable', () => {
})();
});

});
it('should shift click and select a range of rows',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍷

(done: DoneFn) => { inject([], () => {
let fixture: ComponentFixture<any> = 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<any> = TestBed.createComponent(TdDataTableRowClickTestComponent);
let component: TdDataTableRowClickTestComponent = fixture.debugElement.componentInstance;

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.calls.count()).toBe(1);
});
});
})));
});
});

@Component({
Expand All @@ -266,7 +330,7 @@ describe('Component: DataTable', () => {
[columns]="columns">
</td-data-table>`,
})
class TdDataTableBasicComponent {
class TdDataTableBasicTestComponent {
data: any[] = [
{ sku: '1452-2', item: 'Pork Chops', price: 32.11 },
{ sku: '1421-0', item: 'Prime Rib', price: 41.15 },
Expand All @@ -293,3 +357,26 @@ class TdDataTableSelectableTestComponent {
selectable: boolean = false;
multiple: boolean = false;
}

@Component({
template: `
<td-data-table
[data]="data"
[columns]="columns"
(rowClick)="clickEvent()">
</td-data-table>`,
})
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 */
}
}
Loading