Skip to content

Commit

Permalink
(feature): checkbox selection
Browse files Browse the repository at this point in the history
  • Loading branch information
amcdnl committed Dec 2, 2016
1 parent 099e8ee commit 66faf8a
Show file tree
Hide file tree
Showing 15 changed files with 434 additions and 66 deletions.
4 changes: 3 additions & 1 deletion demo/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { Component } from '@angular/core';
<li><a href="#" (click)="state='multi-selection'">Click Mulit Row</a></li>
<li><a href="#" (click)="state='multishift-selection'">Shift Multi Row</a></li>
<li><a href="#" (click)="state='multidisable-selection'">Disable Callback</a></li>
<li><a href="#" (click)="state='chkbox-selection'">Checkbox</a></li>
</ul>
</li>
<li>
Expand Down Expand Up @@ -111,6 +112,7 @@ import { Component } from '@angular/core';
<multi-selection-demo *ngIf="state === 'multi-selection'"></multi-selection-demo>
<multishift-selection-demo *ngIf="state === 'multishift-selection'"></multishift-selection-demo>
<multidisable-selection-demo *ngIf="state === 'multidisable-selection'"></multidisable-selection-demo>
<chkbox-selection-demo *ngIf="state === 'chkbox-selection'"></chkbox-selection-demo>
<!-- Templates -->
<template-ref-demo *ngIf="state === 'templateref'"></template-ref-demo>
Expand Down Expand Up @@ -139,7 +141,7 @@ export class AppComponent {
version: string = APP_VERSION;

constructor() {
// this.state = 'basic-fixed';
// this.state = 'chkbox-selection';
}

}
4 changes: 3 additions & 1 deletion demo/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { MultiSelectionComponent } from './selection/selection-multi';
import { SingleSelectionComponent } from './selection/selection-single';
import { MultiShiftSelectionComponent } from './selection/selection-shift';
import { MultiDisableSelectionComponent } from './selection/selection-disabled';
import { CheckboxSelectionComponent } from './selection/selection-chkbox';

// -- Columns
import { ColumnToggleComponent } from './columns/column-toggle';
Expand Down Expand Up @@ -81,7 +82,8 @@ import { ColumnPinningComponent } from './columns/pinning';
MultiShiftSelectionComponent,
MultiDisableSelectionComponent,
RxDemoComponent,
ContextMenuDemoComponent
ContextMenuDemoComponent,
CheckboxSelectionComponent
],
imports: [BrowserModule, Angular2DataTableModule],
bootstrap: [AppComponent]
Expand Down
101 changes: 101 additions & 0 deletions demo/selection/selection-chkbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Component } from '@angular/core';

@Component({
selector: 'chkbox-selection-demo',
template: `
<div>
<h3>
Checkbox Selection
<small>
<a href="#" (click)="add()">Add</a> |
<a href="#" (click)="update()">Update</a> |
<a href="#" (click)="remove()">Remove</a>
</small>
</h3>
<div style='float:left;width:75%'>
<swui-datatable
style="width: 90%"
class="material"
[rows]="rows"
[columnMode]="'force'"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="'auto'"
[limit]="5"
[selected]="selected"
[selectionType]="'checkbox'"
(activate)="onActivate($event)"
(select)='onSelect($event)'>
<swui-datatable-column
[width]="30"
[sortable]="false"
[canAutoResize]="false"
[draggable]="false"
[resizeable]="false"
[headerCheckboxable]="true"
[checkboxable]="true">
</swui-datatable-column>
<swui-datatable-column name="Name"></swui-datatable-column>
<swui-datatable-column name="Gender"></swui-datatable-column>
<swui-datatable-column name="Company"></swui-datatable-column>
</swui-datatable>
</div>
<div class='selected-column'>
<h4>Selections <small>({{selected?.length}})</small></h4>
<ul>
<li *ngFor='let sel of selected'>
{{sel.name}}
</li>
<li *ngIf="!selected?.length">No Selections</li>
</ul>
</div>
</div>
`
})
export class CheckboxSelectionComponent {

rows = [];
selected = [];

constructor() {
this.fetch((data) => {
this.rows = data;
});
}

fetch(cb) {
const req = new XMLHttpRequest();
req.open('GET', `assets/data/company.json`);

req.onload = () => {
cb(JSON.parse(req.response));
};

req.send();
}

onSelect({ selected }) {
console.log('Select Event', selected, this.selected);

this.selected.splice(0, this.selected.length);
this.selected.push(...selected);
}

onActivate(event) {
console.log('Activate Event', event);
}

add() {
this.selected.push(this.rows[1], this.rows[3]);
}

update() {
this.selected = [ this.rows[1], this.rows[3] ];
}

remove() {
this.selected = [];
}

}
32 changes: 20 additions & 12 deletions docs/api/column-options.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
# Table Column Options

### `name`
### `name`: `string`
Column label. If none specified, it will use the prop value and decamelize it.

### `prop`
### `prop`: `string`
The property to bind the row values to. If `undefined`, it will camelcase the name value.

### `flexGrow`
### `flexGrow`: `number`
The grow factor relative to other columns. Same as the [flex-grow API](http =//www.w3.org/TR/css3-flexbox/).
It will any available extra width and distribute it proportionally according to all columns' flexGrow values. Default value: `0`

### `minWidth`
### `minWidth`: `number`
Minimum width of the column in pixels. Default value: `100`

### `maxWidth`
### `maxWidth`: `number`
Maximum width of the column in pixels. Default value: `undefined`

### `width`
### `width`: `number`
The width of the column by default in pixels. Default value: `150`

### `resizeable`
### `resizeable`: `boolean`
The column can be resized manually by the user. Default value: `true`

### `comparator`
Custom sort comparator, used to apply custom sorting via client-side. See
[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) for more info.

### `sortable`
### `sortable`: `boolean`
Sorting of the row values by this column. Default value: `true`

### `draggable`
### `draggable`: `boolean`
The column can be dragged to re-order. Default value: `true`

### `canAutoResize`
### `canAutoResize`: `boolean`
Whether the column can automatically resize to fill extra space. Default value: `true`

### `cellTemplate`
### `cellTemplate`: `TemplateRef`
Angular TemplateRef allowing you to author custom body cell templates

### `headerTemplate`
### `headerTemplate`: `TemplateRef`
Angular TemplateRef allowing you to author custom header cell templates

### `checkboxable`: `boolean`
Indicates whether the column should show a checkbox component for selection. Only
applicable when the selection mode is `checkbox`.

### `headerCheckboxable`: `boolean`
Indicates whether the column should show a checkbox component in the header cell.
Only applicable when the selection mode is `checkbox`.
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 2.1.0
- Feature: Checkbox selection mode
- Perf: Faster render time by adding css class via host
- Enhancement: Selection mode auto added to host class for easier styling

## 2.0.0
- BREAKING: Rename from `datatable` to `swui-datatable` (#320)
- BREAKING: Redo how row-detail/cell/header templates are described in markup (#304)
Expand Down
30 changes: 27 additions & 3 deletions src/components/body/body-cell.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import { SortDirection } from '../../types';
selector: 'datatable-body-cell',
template: `
<div class="datatable-body-cell-label">
<label
*ngIf="column.checkboxable"
class="datatable-checkbox">
<input
type="checkbox"
[checked]="isSelected"
(change)="onCheckboxChange($event)"
/>
</label>
<span
*ngIf="!column.cellTemplate"
[innerHTML]="value">
Expand All @@ -30,6 +39,7 @@ export class DataTableBodyCellComponent {
@Input() row: any;
@Input() column: any;
@Input() rowHeight: number;
@Input() isSelected: boolean;

@Input() set sorts(val: any[]) {
this._sorts = val;
Expand Down Expand Up @@ -73,10 +83,13 @@ export class DataTableBodyCellComponent {
}

get value(): any {
if (!this.row || !this.column) return '';
const prop = deepValueGetter(this.row, this.column.prop);
if (!this.row || !this.column || !this.column.prop) return '';
const val = deepValueGetter(this.row, this.column.prop);
const userPipe: PipeTransform = this.column.pipe;
return userPipe ? userPipe.transform(prop) : prop;

if(userPipe) return userPipe.transform(val);
if(val !== undefined) return val;
return '';
}

private sortDir: SortDirection;
Expand Down Expand Up @@ -148,6 +161,17 @@ export class DataTableBodyCellComponent {
}
}

onCheckboxChange(event): void {
this.activate.emit({
type: 'checkbox',
event,
row: this.row,
column: this.column,
value: this.value,
cellElement: this.element
});
}

calcSortDir(sorts: any[]): any {
if(!sorts) return;

Expand Down
1 change: 1 addition & 0 deletions src/components/body/body-row.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
*ngFor="let column of colGroup.columns; let ii = index; trackBy: column?.$$id"
tabindex="-1"
[row]="row"
[isSelected]="isSelected"
[column]="column"
[rowHeight]="rowHeight"
(activate)="onActivate($event, ii)">
Expand Down
14 changes: 11 additions & 3 deletions src/components/body/selection.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,20 @@ export class DataTableSelectionComponent {
selectRow(event: KeyboardEvent | MouseEvent, index: number, row: any): void {
if (!this.selectEnabled) return;

const chkbox = this.selectionType === SelectionType.checkbox;
const multiShift = this.selectionType === SelectionType.multiShift;
const multiClick = this.selectionType === SelectionType.multi;
let selected: any[] = [];

if (multiShift || multiClick) {
if (multiShift || multiClick || chkbox) {
if (multiShift && event.shiftKey) {
const newSelected = [...this.selected];
selected = selectRowsBetween(
newSelected, this.rows, index, this.prevIndex, this.getRowSelectedIdx.bind(this));
newSelected,
this.rows,
index,
this.prevIndex,
this.getRowSelectedIdx.bind(this));
} else if (multiShift && !event.shiftKey) {
selected.push(row);
} else {
Expand All @@ -67,8 +72,11 @@ export class DataTableSelectionComponent {

onActivate(model: Model, index: number): void {
const { type, event, row } = model;
const chkbox = this.selectionType === SelectionType.checkbox;
const select = (!chkbox && (type === 'click' || type === 'dblclick')) ||
(chkbox && type === 'checkbox');

if(type === 'click' || type === 'dblclick') {
if(select) {
this.selectRow(event, index, row);
} else if(type === 'keydown') {
if ((<KeyboardEvent>event).keyCode === Keys.return) {
Expand Down
2 changes: 2 additions & 0 deletions src/components/columns/column.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class DataTableColumnDirective {
@Input() minWidth: number;
@Input() width: number;
@Input() maxWidth: number;
@Input() checkboxable: boolean;
@Input() headerCheckboxable: boolean;

@ContentChild(DataTableColumnCellDirective, { read: TemplateRef })
cellTemplate: TemplateRef<any>;
Expand Down
Loading

0 comments on commit 66faf8a

Please sign in to comment.