diff --git a/examples/all.ts b/examples/all.ts index 14480ef5..d37e3f0e 100644 --- a/examples/all.ts +++ b/examples/all.ts @@ -7,6 +7,7 @@ import CardBasicUsage from './components/card/basic_usage'; import CardInlineActions from './components/card/inline_actions'; import ButtonBasicUsage from './components/button/basic_usage'; import CardActionButtons from './components/card/action_buttons'; +import DataTableBasicUsage from './components/data_table/basic_usage'; import DialogBasicUsage from './components/dialog/basic_usage'; import ToolbarBasicUsage from './components/toolbar/basic_usage'; import ToolbarScrollShrink from './components/toolbar/scroll_shrink'; @@ -31,6 +32,7 @@ export const DEMO_DIRECTIVES: Type[] = CONST_EXPR([ CardBasicUsage, CardInlineActions, CardActionButtons, ButtonBasicUsage, CheckboxBasicUsage, CheckboxSyncing, + DataTableBasicUsage, DialogBasicUsage, InputBasicUsage, InputFormBuilder, diff --git a/examples/components/data_table/basic_usage.html b/examples/components/data_table/basic_usage.html new file mode 100644 index 00000000..f5a6740d --- /dev/null +++ b/examples/components/data_table/basic_usage.html @@ -0,0 +1,22 @@ + +
+ + + + + Material + Quantity + Unit price + + + + + {{ material.name }} + {{ material.quantity }} + {{ material.price }} + + + + +
+
diff --git a/examples/components/data_table/basic_usage.ts b/examples/components/data_table/basic_usage.ts new file mode 100644 index 00000000..abc40bbf --- /dev/null +++ b/examples/components/data_table/basic_usage.ts @@ -0,0 +1,15 @@ +import {View, Component} from 'angular2/core'; +import {MATERIAL_DIRECTIVES} from 'ng2-material/all'; + +@Component({selector: 'data-table-basic-usage'}) +@View({ + templateUrl: 'examples/components/data_table/basic_usage.html', + directives: [MATERIAL_DIRECTIVES] +}) +export default class DataTableBasicUsage { + materials: Array = [ + {'name': 'Acrylic (Transparent)', 'quantity': '25', 'price': '$2.90'}, + {'name': 'Plywood (Birch)', 'quantity': '50', 'price': '$1.25'}, + {'name': 'Laminate (Gold on Blue)', 'quantity': '10', 'price': '$2.35'} + ] +} diff --git a/examples/components/data_table/readme.md b/examples/components/data_table/readme.md new file mode 100644 index 00000000..e34bebbc --- /dev/null +++ b/examples/components/data_table/readme.md @@ -0,0 +1 @@ +Table are great to organize datas. diff --git a/ng2-material/all.ts b/ng2-material/all.ts index 7cb0d2bc..4e6aed62 100644 --- a/ng2-material/all.ts +++ b/ng2-material/all.ts @@ -68,6 +68,9 @@ export * from './components/toolbar/toolbar'; import {MdTabs, MdTab} from './components/tabs/tabs'; export * from './components/tabs/tabs'; +import {MdDataTable, MdDataTableTr} from './components/data_table/data_table'; +export * from './components/data_table/data_table'; + import {Media} from "./core/util/media"; export * from './core/util/media'; @@ -97,7 +100,8 @@ export const MATERIAL_DIRECTIVES: Type[] = CONST_EXPR([ MdSubheader, MdSwitch, MdToolbar, - MdTab, MdTabs + MdTab, MdTabs, + MdDataTable, MdDataTableTr ]); /** diff --git a/ng2-material/components.scss b/ng2-material/components.scss index 349195dc..60cd36a1 100644 --- a/ng2-material/components.scss +++ b/ng2-material/components.scss @@ -3,6 +3,7 @@ @import "components/card/card"; @import "components/content/content"; @import "components/checkbox/checkbox"; +@import "components/data_table/data_table"; @import "components/dialog/dialog"; @import "components/divider/divider"; @import "components/icon/icon"; diff --git a/ng2-material/components/data_table/data_table.scss b/ng2-material/components/data_table/data_table.scss new file mode 100644 index 00000000..d0d154aa --- /dev/null +++ b/ng2-material/components/data_table/data_table.scss @@ -0,0 +1,43 @@ +@import "../../core/style/variables"; + +// TODO(jelbourn): This goes away. +@import "../../core/style/default-theme"; + +md-data-table { + display: table; + border-spacing: 0; + border-collapse: collapse; + + md-checkbox { + margin: 0; + } + th { + padding: 22px 12px; + font-size: 12px; + font-weight: 600; + text-align: left; + color: md-color($md-foreground, text); + } + td { + border-top: 1px solid md-color($md-foreground, divider); + padding: 14px 12px; + font-size: 13px; + text-align: right; + color: md-color($md-foreground, secondary-text); + + &.md-data-table__cell--non-numeric { text-align: left; } + } + th:first-child, td:first-child{ + padding-left: 24px; + } + th:last-child, td:last-child{ + padding-right: 24px; + } + + tr:hover td { + background-color: md-color($md-grey, 200); + } + .active td { + background-color: md-color($md-grey, 100); + } +} diff --git a/ng2-material/components/data_table/data_table.ts b/ng2-material/components/data_table/data_table.ts new file mode 100644 index 00000000..64dbdb19 --- /dev/null +++ b/ng2-material/components/data_table/data_table.ts @@ -0,0 +1,151 @@ +import {Component, Inject, forwardRef, ElementRef, AfterContentInit} from 'angular2/core'; +import {Observable} from 'rxjs/Observable'; +import {Observer} from 'rxjs/Observer'; +import 'rxjs/add/operator/filter'; +import 'rxjs/add/operator/share'; +import {MdCheckbox} from '../checkbox/checkbox'; + + +/** + * @name mdDataTable + * + * @description + * The `` component is an enhanced version of data table + * + * Enhancement: + * - selectable row (in progress) + * - sortable column (@todo) + * + * It renders rows and cells as they're set by the user so it doesn't manage the inline editing by itself. + * + * Available attributes are: + * - truncate-header-label-at - (int) Truncate too long header label and prepare a tooltip for the rest of the label (@todo) + * + * Available classes are: + * - `md-data-table.md-data-table--selectable` - Enable one checkbox per line and a master checkbox to rule them all + * - `td.md-sortable` - Enable the order of a column (@todo) + * - `td.md-data-table__cell--non-numeric` - Disable the right alignement of the cells + * + * @usage + * ### Default table + * + * + * + * + * Material + * Quantity + * Unit price + * + * + * + * + * Acrylic (Transparent) + * 25 + * $2.90 + * + * + * + * + * ### Default table with selectable rows + * + * + * + * Material + * Quantity + * Unit price + * + * + * + * + * Acrylic (Transparent) + * 25 + * $2.90 + * + * + * + * + */ + +@Component({ + selector: 'tr', + template: ` + + + + + {{_table.isAllChecked}} + + + `, + directives: [MdCheckbox], + host: { + '[class.active]': 'isActive' + } +}) +export class MdDataTableTr implements AfterContentInit { + isInHeader: boolean = false; + isSelectable: boolean = false; + isActive: boolean = false; + + constructor(@Inject(forwardRef(() => MdDataTable)) private _table: MdDataTable, private _element: ElementRef) { + _table.masterCheckbox$ + .filter(checked => this.isInHeader || checked === true) + .subscribe((checked) => this.isActive = checked); + } + + /** + * Toggle checkbox and style of a row + */ + toggleActive() { + this.isActive = !this.isActive; + if (!this.isActive) { + this._table.toggleAllCheck(false); + } + } + + /** + * @param {ElementRef} element + * + * @returns {any} + */ + static _getMdTableAncestor(element: ElementRef) { + let node = element.nativeElement; + while((node = node.parentNode) && node.localName !== 'md-data-table'); + return node; + } + + ngAfterContentInit() { + this.isInHeader = this._element.nativeElement.parentElement.localName === 'thead'; + + let parent = MdDataTableTr._getMdTableAncestor(this._element); + if (parent !== null) { + this.isSelectable = parent.classList.contains('md-data-table--selectable') + } + } +} + +@Component({ + selector: 'md-data-table', + template: ``, + directives: [MdDataTableTr] +}) +export class MdDataTable { + masterCheckbox$: Observable; + _masterCheckboxObserver: Observer; + + constructor() { + this.masterCheckbox$ = new Observable(observer => this._masterCheckboxObserver = observer) + .share(); + } + + /** + * Toggle all checkbox of the table + * + * @param {boolean} checked + */ + toggleAllCheck(checked: boolean) { + this._masterCheckboxObserver.next(checked); + } +} diff --git a/tsconfig.json b/tsconfig.json index e5c19c2c..a03f219a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,113 +1,115 @@ { - "version": "1.6.0", - "compilerOptions": { - "target": "es5", - "module": "commonjs", - "declaration": false, - "noImplicitAny": false, - "removeComments": true, - "noLib": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "sourceMap": true - }, - "filesGlob": [ - "node_modules/angular2/typings/browser.d.ts", - "dist/ng2-material.d.ts", - "ng2-material/**/*.ts", - "examples/**/*.ts", - "test/**/*.ts" - ], - "compileOnSave": true, - "files": [ - "node_modules/angular2/typings/browser.d.ts", - "dist/ng2-material.d.ts", - "ng2-material/all.ts", - "ng2-material/components/backdrop/backdrop.ts", - "ng2-material/components/button/button.ts", - "ng2-material/components/card/card.ts", - "ng2-material/components/checkbox/checkbox.ts", - "ng2-material/components/content/content.ts", - "ng2-material/components/dialog/dialog.ts", - "ng2-material/components/dialog/dialog_basic.ts", - "ng2-material/components/dialog/dialog_config.ts", - "ng2-material/components/dialog/dialog_container.ts", - "ng2-material/components/dialog/dialog_ref.ts", - "ng2-material/components/divider/divider.ts", - "ng2-material/components/form/messages.ts", - "ng2-material/components/form/validators.ts", - "ng2-material/components/icon/icon.ts", - "ng2-material/components/ink/ink.ts", - "ng2-material/components/input/input.ts", - "ng2-material/components/list/list.ts", - "ng2-material/components/peekaboo/peekaboo.ts", - "ng2-material/components/progress_circular/progress_circular.ts", - "ng2-material/components/progress_linear/progress_linear.ts", - "ng2-material/components/radio/radio_button.ts", - "ng2-material/components/radio/radio_dispatcher.ts", - "ng2-material/components/sidenav/sidenav.ts", - "ng2-material/components/sidenav/sidenav_service.ts", - "ng2-material/components/subheader/subheader.ts", - "ng2-material/components/switcher/switch.ts", - "ng2-material/components/tabs/tabs.ts", - "ng2-material/components/toolbar/toolbar.ts", - "ng2-material/core/key_codes.ts", - "ng2-material/core/util/animate.ts", - "ng2-material/core/util/ink.ts", - "ng2-material/core/util/media.ts", - "ng2-material/core/util/util.ts", - "ng2-material/webpack_all.ts", - "ng2-material/webpack_styles.ts", - "examples/all.ts", - "examples/app.ts", - "examples/components/button/basic_usage.ts", - "examples/components/card/action_buttons.ts", - "examples/components/card/basic_usage.ts", - "examples/components/card/inline_actions.ts", - "examples/components/checkbox/basic_usage.ts", - "examples/components/checkbox/syncing.ts", - "examples/components/dialog/basic_usage.ts", - "examples/components/input/basic_usage.ts", - "examples/components/input/form_builder.ts", - "examples/components/list/basic_usage.ts", - "examples/components/progress_circular/basic_usage.ts", - "examples/components/progress_linear/basic_usage.ts", - "examples/components/radio/basic_usage.ts", - "examples/components/sidenav/basic_usage.ts", - "examples/components/switch/basic_usage.ts", - "examples/components/tabs/dynamic_height.ts", - "examples/components/tabs/dynamic_tabs.ts", - "examples/components/toolbar/basic_usage.ts", - "examples/components/toolbar/scroll_shrink.ts", - "examples/components/whiteframe/basic_usage.ts", - "examples/example.ts", - "examples/highlight.ts", - "examples/routes/component.ts", - "examples/routes/index.ts", - "examples/services/components.ts", - "examples/services/navigation.ts", - "examples/services/version.ts", - "test/bootstrap.ts", - "test/components/backdrop/backdrop_spec.ts", - "test/components/button/button_spec.ts", - "test/components/checkbox/checkbox_spec.ts", - "test/components/dialog/dialog_spec.ts", - "test/components/form/messages_spec.ts", - "test/components/form/validators_spec.ts", - "test/components/ink/ink_spec.ts", - "test/components/input/input_spec.ts", - "test/components/list/list_spec.ts", - "test/components/peekaboo/peekaboo_spec.ts", - "test/components/progress_circular/progress_circular_spec.ts", - "test/components/progress_linear/progress_linear_spec.ts", - "test/components/radio/radio_spec.ts", - "test/components/sidenav/sidenav_service_spec.ts", - "test/components/sidenav/sidenav_spec.ts", - "test/components/subheader/subheader_spec.ts", - "test/components/switch/switch_spec.ts", - "test/components/tabs/tabs_spec.ts", - "test/components/toolbar/toolbar_spec.ts", - "test/test_url_resolver.ts", - "test/util.ts" - ] + "version": "1.6.0", + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "declaration": false, + "noImplicitAny": false, + "removeComments": true, + "noLib": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true + }, + "filesGlob": [ + "node_modules/angular2/typings/browser.d.ts", + "dist/ng2-material.d.ts", + "ng2-material/**/*.ts", + "examples/**/*.ts", + "test/**/*.ts" + ], + "compileOnSave": true, + "files": [ + "node_modules/angular2/typings/browser.d.ts", + "dist/ng2-material.d.ts", + "ng2-material/all.ts", + "ng2-material/components/backdrop/backdrop.ts", + "ng2-material/components/button/button.ts", + "ng2-material/components/card/card.ts", + "ng2-material/components/checkbox/checkbox.ts", + "ng2-material/components/content/content.ts", + "ng2-material/components/data_table/data_table.ts", + "ng2-material/components/dialog/dialog.ts", + "ng2-material/components/dialog/dialog_basic.ts", + "ng2-material/components/dialog/dialog_config.ts", + "ng2-material/components/dialog/dialog_container.ts", + "ng2-material/components/dialog/dialog_ref.ts", + "ng2-material/components/divider/divider.ts", + "ng2-material/components/form/messages.ts", + "ng2-material/components/form/validators.ts", + "ng2-material/components/icon/icon.ts", + "ng2-material/components/ink/ink.ts", + "ng2-material/components/input/input.ts", + "ng2-material/components/list/list.ts", + "ng2-material/components/peekaboo/peekaboo.ts", + "ng2-material/components/progress_circular/progress_circular.ts", + "ng2-material/components/progress_linear/progress_linear.ts", + "ng2-material/components/radio/radio_button.ts", + "ng2-material/components/radio/radio_dispatcher.ts", + "ng2-material/components/sidenav/sidenav.ts", + "ng2-material/components/sidenav/sidenav_service.ts", + "ng2-material/components/subheader/subheader.ts", + "ng2-material/components/switcher/switch.ts", + "ng2-material/components/tabs/tabs.ts", + "ng2-material/components/toolbar/toolbar.ts", + "ng2-material/core/key_codes.ts", + "ng2-material/core/util/animate.ts", + "ng2-material/core/util/ink.ts", + "ng2-material/core/util/media.ts", + "ng2-material/core/util/util.ts", + "ng2-material/webpack_all.ts", + "ng2-material/webpack_styles.ts", + "examples/all.ts", + "examples/app.ts", + "examples/components/button/basic_usage.ts", + "examples/components/card/action_buttons.ts", + "examples/components/card/basic_usage.ts", + "examples/components/card/inline_actions.ts", + "examples/components/checkbox/basic_usage.ts", + "examples/components/checkbox/syncing.ts", + "examples/components/data_table/basic_usage.ts", + "examples/components/dialog/basic_usage.ts", + "examples/components/input/basic_usage.ts", + "examples/components/input/form_builder.ts", + "examples/components/list/basic_usage.ts", + "examples/components/progress_circular/basic_usage.ts", + "examples/components/progress_linear/basic_usage.ts", + "examples/components/radio/basic_usage.ts", + "examples/components/sidenav/basic_usage.ts", + "examples/components/switch/basic_usage.ts", + "examples/components/tabs/dynamic_height.ts", + "examples/components/tabs/dynamic_tabs.ts", + "examples/components/toolbar/basic_usage.ts", + "examples/components/toolbar/scroll_shrink.ts", + "examples/components/whiteframe/basic_usage.ts", + "examples/example.ts", + "examples/highlight.ts", + "examples/routes/component.ts", + "examples/routes/index.ts", + "examples/services/components.ts", + "examples/services/navigation.ts", + "examples/services/version.ts", + "test/bootstrap.ts", + "test/components/backdrop/backdrop_spec.ts", + "test/components/button/button_spec.ts", + "test/components/checkbox/checkbox_spec.ts", + "test/components/dialog/dialog_spec.ts", + "test/components/form/messages_spec.ts", + "test/components/form/validators_spec.ts", + "test/components/ink/ink_spec.ts", + "test/components/input/input_spec.ts", + "test/components/list/list_spec.ts", + "test/components/peekaboo/peekaboo_spec.ts", + "test/components/progress_circular/progress_circular_spec.ts", + "test/components/progress_linear/progress_linear_spec.ts", + "test/components/radio/radio_spec.ts", + "test/components/sidenav/sidenav_service_spec.ts", + "test/components/sidenav/sidenav_spec.ts", + "test/components/subheader/subheader_spec.ts", + "test/components/switch/switch_spec.ts", + "test/components/tabs/tabs_spec.ts", + "test/components/toolbar/toolbar_spec.ts", + "test/test_url_resolver.ts", + "test/util.ts" + ] }