mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-01-09 20:15:07 +00:00
Updated Angular Material elements
Updated the changelog
This commit is contained in:
parent
6fadc29e4c
commit
60ab983730
|
@ -9,7 +9,6 @@ import { ButtonToggleOverviewExample } from 'assets/angular-material-examples/bu
|
|||
import { ButtonTypesExample } from 'assets/angular-material-examples/button-types/button-types-example';
|
||||
import { CardFancyExample } from 'assets/angular-material-examples/card-fancy/card-fancy-example';
|
||||
import { CardOverviewExample } from 'assets/angular-material-examples/card-overview/card-overview-example';
|
||||
import { CdkTableBasicExample } from 'assets/angular-material-examples/cdk-table-basic/cdk-table-basic-example';
|
||||
import { CheckboxConfigurableExample } from 'assets/angular-material-examples/checkbox-configurable/checkbox-configurable-example';
|
||||
import { CheckboxOverviewExample } from 'assets/angular-material-examples/checkbox-overview/checkbox-overview-example';
|
||||
import { ChipsInputExample } from 'assets/angular-material-examples/chips-input/chips-input-example';
|
||||
|
@ -111,8 +110,6 @@ import { FormFieldLabelExample } from 'assets/angular-material-examples/form-fie
|
|||
import { AutocompleteOptgroupExample } from 'assets/angular-material-examples/autocomplete-optgroup/autocomplete-optgroup-example';
|
||||
import { BadgeOverviewExample } from 'assets/angular-material-examples/badge-overview/badge-overview-example';
|
||||
import { BottomSheetOverviewExample, BottomSheetOverviewExampleSheet } from 'assets/angular-material-examples/bottom-sheet-overview/bottom-sheet-overview-example';
|
||||
import { CdkTreeFlatExample } from 'assets/angular-material-examples/cdk-tree-flat/cdk-tree-flat-example';
|
||||
import { CdkTreeNestedExample } from 'assets/angular-material-examples/cdk-tree-nested/cdk-tree-nested-example';
|
||||
import { ChipsAutocompleteExample } from 'assets/angular-material-examples/chips-autocomplete/chips-autocomplete-example';
|
||||
import { DatepickerColorExample } from 'assets/angular-material-examples/datepicker-color/datepicker-color-example';
|
||||
import { DatepickerCustomHeaderExample, ExampleHeader } from 'assets/angular-material-examples/datepicker-custom-header/datepicker-custom-header-example';
|
||||
|
@ -143,7 +140,6 @@ import { TreeDynamicExample } from 'assets/angular-material-examples/tree-dynami
|
|||
import { TreeFlatOverviewExample } from 'assets/angular-material-examples/tree-flat-overview/tree-flat-overview-example';
|
||||
import { TreeLoadmoreExample } from 'assets/angular-material-examples/tree-loadmore/tree-loadmore-example';
|
||||
import { TreeNestedOverviewExample } from 'assets/angular-material-examples/tree-nested-overview/tree-nested-overview-example';
|
||||
import { CdkTableBasicFlexExample } from 'assets/angular-material-examples/cdk-table-basic-flex/cdk-table-basic-flex-example';
|
||||
import { StepperVerticalExample } from 'assets/angular-material-examples/stepper-vertical/stepper-vertical-example';
|
||||
import { TabGroupBasicExample } from 'assets/angular-material-examples/tab-group-basic/tab-group-basic-example';
|
||||
import { TabGroupAsyncExample } from 'assets/angular-material-examples/tab-group-async/tab-group-async-example';
|
||||
|
@ -169,6 +165,14 @@ import { TableStickyComplexExample } from 'assets/angular-material-examples/tabl
|
|||
import { TableStickyComplexFlexExample } from 'assets/angular-material-examples/table-sticky-complex-flex/table-sticky-complex-flex-example';
|
||||
import { TableStickyFooterExample } from 'assets/angular-material-examples/table-sticky-footer/table-sticky-footer-example';
|
||||
import { TableStickyHeaderExample } from 'assets/angular-material-examples/table-sticky-header/table-sticky-header-example';
|
||||
import { ButtonToggleAppearanceExample } from 'assets/angular-material-examples/button-toggle-appearance/button-toggle-appearance-example';
|
||||
import { RippleOverviewExample } from 'assets/angular-material-examples/ripple-overview/ripple-overview-example';
|
||||
import { StepperLabelPositionBottomExample } from 'assets/angular-material-examples/stepper-label-position-bottom/stepper-label-position-bottom-example';
|
||||
import { StepperStatesExample } from 'assets/angular-material-examples/stepper-states/stepper-states-example';
|
||||
import { StepperErrorsExample } from 'assets/angular-material-examples/stepper-errors/stepper-errors-example';
|
||||
import { TabGroupAlignExample } from 'assets/angular-material-examples/tab-group-align/tab-group-align-example';
|
||||
import { SimpleColumn, TableSimpleColumnExample } from 'assets/angular-material-examples/table-simple-column/table-simple-column-example';
|
||||
import { TableWrappedExample, WrapperTable } from 'assets/angular-material-examples/table-wrapped/table-wrapped-example';
|
||||
|
||||
export const COMPONENT_MAP = {
|
||||
'autocomplete' : [
|
||||
|
@ -191,20 +195,13 @@ export const COMPONENT_MAP = {
|
|||
],
|
||||
'button-toggle' : [
|
||||
'button-toggle-overview',
|
||||
'button-toggle-appearance',
|
||||
'button-toggle-exclusive'
|
||||
],
|
||||
'card' : [
|
||||
'card-overview',
|
||||
'card-fancy'
|
||||
],
|
||||
// 'cdk-table' : [
|
||||
// 'cdk-table-basic',
|
||||
// 'cdk-table-basic-flex',
|
||||
// 'cdk-table-flat'
|
||||
// ],
|
||||
// 'cdk-tree' : [
|
||||
// 'cdk-tree-nested'
|
||||
// ],
|
||||
'checkbox' : [
|
||||
'checkbox-overview',
|
||||
'checkbox-configurable'
|
||||
|
@ -307,6 +304,9 @@ export const COMPONENT_MAP = {
|
|||
'progress-spinner-overview',
|
||||
'progress-spinner-configurable'
|
||||
],
|
||||
'ripples' : [
|
||||
'ripple-overview'
|
||||
],
|
||||
'radio-button' : [
|
||||
'radio-overview',
|
||||
'radio-ng-model'
|
||||
|
@ -357,7 +357,10 @@ export const COMPONENT_MAP = {
|
|||
'stepper' : [
|
||||
'stepper-overview',
|
||||
'stepper-editable',
|
||||
'stepper-errors',
|
||||
'stepper-label-position-bottom',
|
||||
'stepper-optional',
|
||||
'stepper-states',
|
||||
'stepper-vertical'
|
||||
],
|
||||
'table' : [
|
||||
|
@ -373,16 +376,19 @@ export const COMPONENT_MAP = {
|
|||
'table-pagination',
|
||||
'table-row-context',
|
||||
'table-selection',
|
||||
'table-simple-column',
|
||||
'table-sorting',
|
||||
'table-sticky-columns',
|
||||
'table-sticky-complex',
|
||||
'table-sticky-complex-flex',
|
||||
'table-sticky-header',
|
||||
'table-sticky-footer',
|
||||
'table-wrapped'
|
||||
],
|
||||
'tabs' : [
|
||||
'tab-group-basic',
|
||||
'tab-group-async',
|
||||
'tab-group-align',
|
||||
'tab-group-custom-label',
|
||||
'tab-group-dynamic',
|
||||
'tab-group-dynamic-height',
|
||||
|
@ -460,6 +466,10 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Basic buttons',
|
||||
component: ButtonOverviewExample
|
||||
},
|
||||
'button-toggle-appearance' : {
|
||||
title : 'Button toggle appearance',
|
||||
component: ButtonToggleAppearanceExample
|
||||
},
|
||||
'button-toggle-exclusive' : {
|
||||
title : 'Exclusive selection',
|
||||
component: ButtonToggleExclusiveExample
|
||||
|
@ -480,22 +490,6 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Basic cards',
|
||||
component: CardOverviewExample
|
||||
},
|
||||
'cdk-table-basic' : {
|
||||
title : 'Basic CDK data-table',
|
||||
component: CdkTableBasicExample
|
||||
},
|
||||
'cdk-table-basic-flex' : {
|
||||
title : 'Basic use of `<cdk-table>` (uses display flex)',
|
||||
component: CdkTableBasicFlexExample
|
||||
},
|
||||
'cdk-tree-flat' : {
|
||||
title : 'Tree with flat nodes',
|
||||
component: CdkTreeFlatExample
|
||||
},
|
||||
'cdk-tree-nested' : {
|
||||
title : 'Tree with nested nodes',
|
||||
component: CdkTreeNestedExample
|
||||
},
|
||||
'checkbox-configurable' : {
|
||||
title : 'Configurable checkbox',
|
||||
component: CheckboxConfigurableExample
|
||||
|
@ -787,6 +781,10 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Basic radios',
|
||||
component: RadioOverviewExample
|
||||
},
|
||||
'ripple-overview' : {
|
||||
title : 'MatRipple basic usage',
|
||||
component: RippleOverviewExample
|
||||
},
|
||||
'select-custom-trigger' : {
|
||||
title : 'Select with custom trigger text',
|
||||
component: SelectCustomTriggerExample
|
||||
|
@ -921,6 +919,14 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Stepper with editable steps',
|
||||
component: StepperEditableExample
|
||||
},
|
||||
'stepper-errors' : {
|
||||
title : 'Stepper that displays errors in the steps\n',
|
||||
component: StepperErrorsExample
|
||||
},
|
||||
'stepper-label-position-bottom' : {
|
||||
title : 'Stepper label position bottom',
|
||||
component: StepperLabelPositionBottomExample
|
||||
},
|
||||
'stepper-optional' : {
|
||||
title : 'Stepper with optional steps',
|
||||
component: StepperOptionalExample
|
||||
|
@ -929,6 +935,10 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Stepper overview',
|
||||
component: StepperOverviewExample
|
||||
},
|
||||
'stepper-states' : {
|
||||
title : 'Stepper with customized states',
|
||||
component: StepperStatesExample
|
||||
},
|
||||
'stepper-vertical' : {
|
||||
title : 'Stepper vertical',
|
||||
component: StepperVerticalExample
|
||||
|
@ -937,15 +947,15 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Basic table',
|
||||
component: TableBasicExample
|
||||
},
|
||||
'table-basic-flex' : {
|
||||
'table-basic-flex' : {
|
||||
title : 'Basic use of `<mat-table>` (uses display flex)',
|
||||
component: TableBasicFlexExample
|
||||
},
|
||||
'table-dynamic-columns' : {
|
||||
'table-dynamic-columns' : {
|
||||
title : 'Table dynamically changing the columns displayed',
|
||||
component: TableDynamicColumnsExample
|
||||
},
|
||||
'table-expandable-rows' : {
|
||||
'table-expandable-rows' : {
|
||||
title : 'Table with expandable rows',
|
||||
component: TableExpandableRowsExample
|
||||
},
|
||||
|
@ -961,7 +971,7 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Table retrieving data through HTTP',
|
||||
component: TableHttpExample
|
||||
},
|
||||
'table-multiple-header-footer' : {
|
||||
'table-multiple-header-footer' : {
|
||||
title : 'Table with multiple header and footer rows',
|
||||
component: TableMultipleHeaderFooterExample
|
||||
},
|
||||
|
@ -973,7 +983,7 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Table with pagination',
|
||||
component: TablePaginationExample
|
||||
},
|
||||
'table-row-context' : {
|
||||
'table-row-context' : {
|
||||
title : 'Table showing each row context properties',
|
||||
component: TableRowContextExample
|
||||
},
|
||||
|
@ -981,30 +991,42 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Table with selection',
|
||||
component: TableSelectionExample
|
||||
},
|
||||
'table-simple-column' : {
|
||||
title : 'Table with a custom column component for easy column definition reuse',
|
||||
component: TableSimpleColumnExample
|
||||
},
|
||||
'table-sorting' : {
|
||||
title : 'Table with sorting',
|
||||
component: TableSortingExample
|
||||
},
|
||||
'table-sticky-columns' : {
|
||||
'table-sticky-columns' : {
|
||||
title : 'Table with a sticky columns',
|
||||
component: TableStickyColumnsExample
|
||||
},
|
||||
'table-sticky-complex' : {
|
||||
'table-sticky-complex' : {
|
||||
title : 'Tables with toggle-able sticky headers, footers, and columns',
|
||||
component: TableStickyComplexExample
|
||||
},
|
||||
'table-sticky-complex-flex' : {
|
||||
'table-sticky-complex-flex' : {
|
||||
title : 'Flex-layout tables with toggle-able sticky headers, footers, and columns',
|
||||
component: TableStickyComplexFlexExample
|
||||
},
|
||||
'table-sticky-footer' : {
|
||||
'table-sticky-footer' : {
|
||||
title : 'Table with a sticky footer',
|
||||
component: TableStickyFooterExample
|
||||
},
|
||||
'table-sticky-header' : {
|
||||
'table-sticky-header' : {
|
||||
title : 'Table with sticky header',
|
||||
component: TableStickyHeaderExample
|
||||
},
|
||||
'table-wrapped' : {
|
||||
title : 'Table example that shows how to wrap a table component for definition and behavior reuse',
|
||||
component: TableWrappedExample
|
||||
},
|
||||
'tab-group-align' : {
|
||||
title : 'Tab group with aligned labels',
|
||||
component: TabGroupAlignExample
|
||||
},
|
||||
'tab-group-basic' : {
|
||||
title : 'Basic use of the tab group',
|
||||
component: TabGroupBasicExample
|
||||
|
@ -1065,11 +1087,11 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Basic toolbar',
|
||||
component: ToolbarOverviewExample
|
||||
},
|
||||
'tooltip-auto-hide' : {
|
||||
'tooltip-auto-hide' : {
|
||||
title : 'Tooltip that demonstrates auto-hiding when it clips out of its scrolling container',
|
||||
component: TooltipAutoHideExample
|
||||
},
|
||||
'tooltip-custom-class' : {
|
||||
'tooltip-custom-class' : {
|
||||
title : 'Tooltip that can have a custom class applied',
|
||||
component: TooltipCustomClassExample
|
||||
},
|
||||
|
@ -1077,7 +1099,7 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Tooltip with a show and hide delay',
|
||||
component: TooltipDelayExample
|
||||
},
|
||||
'tooltip-disabled' : {
|
||||
'tooltip-disabled' : {
|
||||
title : 'Tooltip that can be disabled',
|
||||
component: TooltipDisabledExample
|
||||
},
|
||||
|
@ -1085,7 +1107,7 @@ export const EXAMPLE_COMPONENTS = {
|
|||
title : 'Tooltip that can be manually shown/hidden',
|
||||
component: TooltipManualExample
|
||||
},
|
||||
'tooltip-message' : {
|
||||
'tooltip-message' : {
|
||||
title : 'Tooltip with a changing message',
|
||||
component: TooltipMessageExample
|
||||
},
|
||||
|
@ -1135,13 +1157,10 @@ export const EXAMPLE_LIST = [
|
|||
ButtonOverviewExample,
|
||||
ButtonToggleExclusiveExample,
|
||||
ButtonToggleOverviewExample,
|
||||
ButtonToggleAppearanceExample,
|
||||
ButtonTypesExample,
|
||||
CardFancyExample,
|
||||
CardOverviewExample,
|
||||
CdkTableBasicExample,
|
||||
CdkTableBasicFlexExample,
|
||||
CdkTreeFlatExample,
|
||||
CdkTreeNestedExample,
|
||||
CheckboxConfigurableExample,
|
||||
CheckboxOverviewExample,
|
||||
ChipsAutocompleteExample,
|
||||
|
@ -1212,6 +1231,7 @@ export const EXAMPLE_LIST = [
|
|||
ProgressSpinnerOverviewExample,
|
||||
RadioNgModelExample,
|
||||
RadioOverviewExample,
|
||||
RippleOverviewExample,
|
||||
SelectCustomTriggerExample,
|
||||
SelectDisabledExample,
|
||||
SelectErrorStateMatcherExample,
|
||||
|
@ -1245,8 +1265,11 @@ export const EXAMPLE_LIST = [
|
|||
SnackBarPositionExample,
|
||||
SortOverviewExample,
|
||||
StepperEditableExample,
|
||||
StepperErrorsExample,
|
||||
StepperLabelPositionBottomExample,
|
||||
StepperOptionalExample,
|
||||
StepperOverviewExample,
|
||||
StepperStatesExample,
|
||||
StepperVerticalExample,
|
||||
TableBasicExample,
|
||||
TableBasicFlexExample,
|
||||
|
@ -1260,12 +1283,15 @@ export const EXAMPLE_LIST = [
|
|||
TablePaginationExample,
|
||||
TableRowContextExample,
|
||||
TableSelectionExample,
|
||||
TableSimpleColumnExample, SimpleColumn,
|
||||
TableSortingExample,
|
||||
TableStickyColumnsExample,
|
||||
TableStickyComplexExample,
|
||||
TableStickyComplexFlexExample,
|
||||
TableStickyFooterExample,
|
||||
TableStickyHeaderExample,
|
||||
TableWrappedExample, WrapperTable,
|
||||
TabGroupAlignExample,
|
||||
TabGroupBasicExample,
|
||||
TabGroupAsyncExample,
|
||||
TabGroupCustomLabelExample,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { CdkTableModule } from '@angular/cdk/table';
|
||||
import { CdkTreeModule } from '@angular/cdk/tree';
|
||||
import {
|
||||
MatAutocompleteModule, MatBadgeModule, MatBottomSheetModule, MatButtonModule,
|
||||
MatButtonToggleModule, MatCardModule, MatCheckboxModule, MatChipsModule, MatDatepickerModule,
|
||||
|
@ -15,8 +13,6 @@ import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
|||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CdkTableModule,
|
||||
CdkTreeModule,
|
||||
MatAutocompleteModule,
|
||||
MatBadgeModule,
|
||||
MatBottomSheetModule,
|
||||
|
@ -55,8 +51,6 @@ import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
|||
MatTreeModule
|
||||
],
|
||||
exports: [
|
||||
CdkTableModule,
|
||||
CdkTreeModule,
|
||||
MatAutocompleteModule,
|
||||
MatBadgeModule,
|
||||
MatBottomSheetModule,
|
||||
|
|
|
@ -63,9 +63,9 @@
|
|||
<div class="new">
|
||||
<span class="title">New</span>
|
||||
<ul>
|
||||
<li>Updated Angular to 7.0.0-rc.0</li>
|
||||
<li>Updated Angular Material to 7.0.0-rc.1</li>
|
||||
<li>Updated Typescript to 3.1.1</li>
|
||||
<li>Updated Angular to 7.0.0</li>
|
||||
<li>Updated Angular Material to 7.0.0</li>
|
||||
<li>Updated Typescript to 3.1.3</li>
|
||||
<li>Updated various other libraries</li>
|
||||
<li>Modernization:
|
||||
<ul>
|
||||
|
|
|
@ -329,11 +329,11 @@ export const navigation: FuseNavigation[] = [
|
|||
url : '/pages/profile'
|
||||
},
|
||||
{
|
||||
id : 'search',
|
||||
title: 'Search',
|
||||
type : 'collapsable',
|
||||
icon : 'search',
|
||||
children : [
|
||||
id : 'search',
|
||||
title : 'Search',
|
||||
type : 'collapsable',
|
||||
icon : 'search',
|
||||
children: [
|
||||
{
|
||||
id : 'search-classic',
|
||||
title: 'Classic',
|
||||
|
@ -345,7 +345,7 @@ export const navigation: FuseNavigation[] = [
|
|||
title: 'Modern',
|
||||
type : 'item',
|
||||
url : '/pages/search/modern'
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -793,6 +793,12 @@ export const navigation: FuseNavigation[] = [
|
|||
title: 'Progress bar',
|
||||
type : 'item',
|
||||
url : '/angular-material-elements/progress-bar'
|
||||
},
|
||||
{
|
||||
id : 'ripples',
|
||||
title: 'Ripples',
|
||||
type : 'item',
|
||||
url : '/angular-material-elements/ripples'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -18,6 +18,7 @@ export const _filter = (opt: string[], value: string): string[] => {
|
|||
* @title Option groups autocomplete
|
||||
*/
|
||||
@Component({
|
||||
selector: 'autocomplete-optgroup-example',
|
||||
templateUrl: './autocomplete-optgroup-example.html',
|
||||
styleUrls: ['./autocomplete-optgroup-example.css'],
|
||||
})
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<p>You have receive a file called "cat-picture.jpeg".</p>
|
||||
<p>You have received a file called "cat-picture.jpeg".</p>
|
||||
|
||||
<button mat-raised-button (click)="openBottomSheet()">Open file</button>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/** No CSS for this example */
|
|
@ -0,0 +1,17 @@
|
|||
<p>
|
||||
Default appearance:
|
||||
<mat-button-toggle-group name="fontStyle" aria-label="Font Style">
|
||||
<mat-button-toggle value="bold">Bold</mat-button-toggle>
|
||||
<mat-button-toggle value="italic">Italic</mat-button-toggle>
|
||||
<mat-button-toggle value="underline">Underline</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Legacy appearance:
|
||||
<mat-button-toggle-group appearance="legacy" name="fontStyle" aria-label="Font Style">
|
||||
<mat-button-toggle value="bold">Bold</mat-button-toggle>
|
||||
<mat-button-toggle value="italic">Italic</mat-button-toggle>
|
||||
<mat-button-toggle value="underline">Underline</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</p>
|
|
@ -0,0 +1,11 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
/**
|
||||
* @title Button toggle appearance
|
||||
*/
|
||||
@Component({
|
||||
selector: 'button-toggle-appearance-example',
|
||||
templateUrl: 'button-toggle-appearance-example.html',
|
||||
styleUrls: ['button-toggle-appearance-example.css'],
|
||||
})
|
||||
export class ButtonToggleAppearanceExample {}
|
|
@ -1,4 +1,4 @@
|
|||
.button-row button,
|
||||
.button-row a {
|
||||
.example-button-row button,
|
||||
.example-button-row a {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<h3>Basic Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-button>Basic</button>
|
||||
<button mat-button color="primary">Primary</button>
|
||||
<button mat-button color="accent">Accent</button>
|
||||
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
|
||||
<h3>Raised Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-raised-button>Basic</button>
|
||||
<button mat-raised-button color="primary">Primary</button>
|
||||
<button mat-raised-button color="accent">Accent</button>
|
||||
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
|
||||
<h3>Stroked Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-stroked-button>Basic</button>
|
||||
<button mat-stroked-button color="primary">Primary</button>
|
||||
<button mat-stroked-button color="accent">Accent</button>
|
||||
|
@ -29,7 +29,7 @@
|
|||
</div>
|
||||
|
||||
<h3>Flat Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-flat-button>Basic</button>
|
||||
<button mat-flat-button color="primary">Primary</button>
|
||||
<button mat-flat-button color="accent">Accent</button>
|
||||
|
@ -39,7 +39,7 @@
|
|||
</div>
|
||||
|
||||
<h3>Icon Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-icon-button>
|
||||
<mat-icon aria-label="Example icon-button with a heart icon">favorite</mat-icon>
|
||||
</button>
|
||||
|
@ -58,7 +58,7 @@
|
|||
</div>
|
||||
|
||||
<h3>Fab Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-fab>Basic</button>
|
||||
<button mat-fab color="primary">Primary</button>
|
||||
<button mat-fab color="accent">Accent</button>
|
||||
|
@ -71,7 +71,7 @@
|
|||
</div>
|
||||
|
||||
<h3>Mini Fab Buttons</h3>
|
||||
<div class="button-row">
|
||||
<div class="example-button-row">
|
||||
<button mat-mini-fab>Basic</button>
|
||||
<button mat-mini-fab color="primary">Primary</button>
|
||||
<button mat-mini-fab color="accent">Accent</button>
|
||||
|
@ -81,4 +81,4 @@
|
|||
<mat-icon aria-label="Example icon-button with a heart icon">favorite</mat-icon>
|
||||
</button>
|
||||
<a mat-mini-fab routerLink=".">Link</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/**
|
||||
* Add basic flex styling so that the cells evenly space themselves in the row.
|
||||
*/
|
||||
cdk-row, cdk-header-row, cdk-footer-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
cdk-cell, cdk-header-cell, cdk-footer-cell {
|
||||
flex: 1;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<cdk-table [dataSource]="dataSource">
|
||||
<!-- Position Column -->
|
||||
<ng-container cdkColumnDef="position">
|
||||
<cdk-header-cell *cdkHeaderCellDef> No. </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let element"> {{element.position}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container cdkColumnDef="name">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Name </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let element"> {{element.name}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container cdkColumnDef="weight">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Weight </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let element"> {{element.weight}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container cdkColumnDef="symbol">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Symbol </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let element"> {{element.symbol}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<cdk-header-row *cdkHeaderRowDef="displayedColumns"></cdk-header-row>
|
||||
<cdk-row *cdkRowDef="let row; columns: displayedColumns;"></cdk-row>
|
||||
</cdk-table>
|
|
@ -1,55 +0,0 @@
|
|||
import {DataSource} from '@angular/cdk/collections';
|
||||
import {Component} from '@angular/core';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
|
||||
export interface PeriodicElement {
|
||||
name: string;
|
||||
position: number;
|
||||
symbol: string;
|
||||
weight: number;
|
||||
}
|
||||
|
||||
const ELEMENT_DATA: PeriodicElement[] = [
|
||||
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
|
||||
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
|
||||
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
|
||||
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
|
||||
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
|
||||
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
|
||||
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
|
||||
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
|
||||
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
|
||||
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
|
||||
];
|
||||
|
||||
/**
|
||||
* @title Basic use of `<cdk-table>` (uses display flex)
|
||||
*/
|
||||
@Component({
|
||||
selector: 'cdk-table-basic-flex-example',
|
||||
styleUrls: ['cdk-table-basic-flex-example.css'],
|
||||
templateUrl: 'cdk-table-basic-flex-example.html',
|
||||
})
|
||||
export class CdkTableBasicFlexExample {
|
||||
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
|
||||
dataSource = new ExampleDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data source to provide what data should be rendered in the table. Note that the data source
|
||||
* can retrieve its data in any way. In this case, the data source is provided a reference
|
||||
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage
|
||||
* the underlying data. Instead, it only needs to take the data and send the table exactly what
|
||||
* should be rendered.
|
||||
*/
|
||||
export class ExampleDataSource extends DataSource<PeriodicElement> {
|
||||
/** Stream of data that is provided to the table. */
|
||||
data = new BehaviorSubject<PeriodicElement[]>(ELEMENT_DATA);
|
||||
|
||||
/** Connect function called by the table to retrieve one stream containing the data to render. */
|
||||
connect(): Observable<PeriodicElement[]> {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
disconnect() {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<table cdk-table [dataSource]="dataSource">
|
||||
<!-- Position Column -->
|
||||
<ng-container cdkColumnDef="position">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> No. </th>
|
||||
<td cdk-cell *cdkCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container cdkColumnDef="name">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Name </th>
|
||||
<td cdk-cell *cdkCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container cdkColumnDef="weight">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Weight </th>
|
||||
<td cdk-cell *cdkCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container cdkColumnDef="symbol">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Symbol </th>
|
||||
<td cdk-cell *cdkCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr cdk-header-row *cdkHeaderRowDef="displayedColumns"></tr>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
|
@ -1,55 +0,0 @@
|
|||
import {DataSource} from '@angular/cdk/collections';
|
||||
import {Component} from '@angular/core';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
|
||||
export interface PeriodicElement {
|
||||
name: string;
|
||||
position: number;
|
||||
weight: number;
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
const ELEMENT_DATA: PeriodicElement[] = [
|
||||
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
|
||||
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
|
||||
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
|
||||
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
|
||||
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
|
||||
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
|
||||
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
|
||||
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
|
||||
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
|
||||
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
|
||||
];
|
||||
|
||||
/**
|
||||
* @title Basic CDK data-table
|
||||
*/
|
||||
@Component({
|
||||
selector: 'cdk-table-basic-example',
|
||||
styleUrls: ['cdk-table-basic-example.css'],
|
||||
templateUrl: 'cdk-table-basic-example.html',
|
||||
})
|
||||
export class CdkTableBasicExample {
|
||||
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
|
||||
dataSource = new ExampleDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data source to provide what data should be rendered in the table. Note that the data source
|
||||
* can retrieve its data in any way. In this case, the data source is provided a reference
|
||||
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage
|
||||
* the underlying data. Instead, it only needs to take the data and send the table exactly what
|
||||
* should be rendered.
|
||||
*/
|
||||
export class ExampleDataSource extends DataSource<PeriodicElement> {
|
||||
/** Stream of data that is provided to the table. */
|
||||
data = new BehaviorSubject<PeriodicElement[]>(ELEMENT_DATA);
|
||||
|
||||
/** Connect function called by the table to retrieve one stream containing the data to render. */
|
||||
connect(): Observable<PeriodicElement[]> {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
disconnect() {}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
.example-tree-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
|
||||
<cdk-tree-node *cdkTreeNodeDef="let node" cdkTreeNodePadding class="example-tree-node">
|
||||
<button mat-icon-button disabled></button>
|
||||
{{node.filename}}: {{node.type}}
|
||||
</cdk-tree-node>
|
||||
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChild" cdkTreeNodePadding class="example-tree-node">
|
||||
<button mat-icon-button [attr.aria-label]="'toggle ' + node.filename" cdkTreeNodeToggle>
|
||||
<mat-icon class="mat-icon-rtl-mirror">
|
||||
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
|
||||
</mat-icon>
|
||||
</button>
|
||||
{{node.filename}}: {{node.type}}
|
||||
</cdk-tree-node>
|
||||
</cdk-tree>
|
|
@ -1,149 +0,0 @@
|
|||
import {FlatTreeControl} from '@angular/cdk/tree';
|
||||
import {Component, Injectable} from '@angular/core';
|
||||
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';
|
||||
import {BehaviorSubject, Observable, of as observableOf} from 'rxjs';
|
||||
|
||||
/**
|
||||
* File node data with nested structure.
|
||||
* Each node has a filename, and a type or a list of children.
|
||||
*/
|
||||
export class FileNode {
|
||||
children: FileNode[];
|
||||
filename: string;
|
||||
type: any;
|
||||
}
|
||||
|
||||
/** Flat node with expandable and level information */
|
||||
export class FileFlatNode {
|
||||
constructor(
|
||||
public expandable: boolean, public filename: string, public level: number, public type: any) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* The file structure tree data in string. The data could be parsed into a Json object
|
||||
*/
|
||||
const TREE_DATA = JSON.stringify({
|
||||
Applications: {
|
||||
Calendar: 'app',
|
||||
Chrome: 'app',
|
||||
Webstorm: 'app'
|
||||
},
|
||||
Documents: {
|
||||
angular: {
|
||||
src: {
|
||||
compiler: 'ts',
|
||||
core: 'ts'
|
||||
}
|
||||
},
|
||||
material2: {
|
||||
src: {
|
||||
button: 'ts',
|
||||
checkbox: 'ts',
|
||||
input: 'ts'
|
||||
}
|
||||
}
|
||||
},
|
||||
Downloads: {
|
||||
October: 'pdf',
|
||||
November: 'pdf',
|
||||
Tutorial: 'html'
|
||||
},
|
||||
Pictures: {
|
||||
'Photo Booth Library': {
|
||||
Contents: 'dir',
|
||||
Pictures: 'dir'
|
||||
},
|
||||
Sun: 'png',
|
||||
Woods: 'jpg'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* File database, it can build a tree structured Json object from string.
|
||||
* Each node in Json object represents a file or a directory. For a file, it has filename and type.
|
||||
* For a directory, it has filename and children (a list of files or directories).
|
||||
* The input will be a json object string, and the output is a list of `FileNode` with nested
|
||||
* structure.
|
||||
*/
|
||||
@Injectable()
|
||||
export class FileDatabase {
|
||||
dataChange = new BehaviorSubject<FileNode[]>([]);
|
||||
|
||||
get data(): FileNode[] { return this.dataChange.value; }
|
||||
|
||||
constructor() {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
// Parse the string to json object.
|
||||
const dataObject = JSON.parse(TREE_DATA);
|
||||
|
||||
// Build the tree nodes from Json object. The result is a list of `FileNode` with nested
|
||||
// file node as children.
|
||||
const data = this.buildFileTree(dataObject, 0);
|
||||
|
||||
// Notify the change.
|
||||
this.dataChange.next(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
|
||||
* The return value is the list of `FileNode`.
|
||||
*/
|
||||
buildFileTree(obj: object, level: number): FileNode[] {
|
||||
return Object.keys(obj).reduce<FileNode[]>((accumulator, key) => {
|
||||
const value = obj[key];
|
||||
const node = new FileNode();
|
||||
node.filename = key;
|
||||
|
||||
if (value != null) {
|
||||
if (typeof value === 'object') {
|
||||
node.children = this.buildFileTree(value, level + 1);
|
||||
} else {
|
||||
node.type = value;
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator.concat(node);
|
||||
}, []);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title Tree with flat nodes
|
||||
*/
|
||||
@Component({
|
||||
selector: 'cdk-tree-flat-example',
|
||||
templateUrl: 'cdk-tree-flat-example.html',
|
||||
styleUrls: ['cdk-tree-flat-example.css'],
|
||||
providers: [FileDatabase]
|
||||
})
|
||||
export class CdkTreeFlatExample {
|
||||
treeControl: FlatTreeControl<FileFlatNode>;
|
||||
treeFlattener: MatTreeFlattener<FileNode, FileFlatNode>;
|
||||
dataSource: MatTreeFlatDataSource<FileNode, FileFlatNode>;
|
||||
|
||||
constructor(database: FileDatabase) {
|
||||
this.treeFlattener = new MatTreeFlattener(this.transformer, this._getLevel,
|
||||
this._isExpandable, this._getChildren);
|
||||
this.treeControl = new FlatTreeControl<FileFlatNode>(this._getLevel, this._isExpandable);
|
||||
this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
|
||||
|
||||
database.dataChange.subscribe(data => {
|
||||
this.dataSource.data = data;
|
||||
});
|
||||
}
|
||||
|
||||
hasChild = (_: number, _nodeData: FileFlatNode) => _nodeData.expandable;
|
||||
|
||||
transformer = (node: FileNode, level: number) => {
|
||||
return new FileFlatNode(!!node.children, node.filename, level, node.type);
|
||||
}
|
||||
|
||||
private _getLevel = (node: FileFlatNode) => node.level;
|
||||
|
||||
private _isExpandable = (node: FileFlatNode) => node.expandable;
|
||||
|
||||
private _getChildren = (node: FileNode): Observable<FileNode[]> => observableOf(node.children);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
.example-tree-invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.example-tree ul,
|
||||
.example-tree li {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.example-tree-node {
|
||||
display: block;
|
||||
padding-left: 40px;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<cdk-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl">
|
||||
<cdk-nested-tree-node *cdkTreeNodeDef="let node" class="example-tree-node">
|
||||
<button mat-icon-button disabled></button>
|
||||
{{node.filename}}: {{node.type}}
|
||||
</cdk-nested-tree-node>
|
||||
<cdk-nested-tree-node *cdkTreeNodeDef="let node; when: hasNestedChild" class="example-tree-node">
|
||||
<button mat-icon-button [attr.aria-label]="'toggle ' + node.filename" cdkTreeNodeToggle>
|
||||
<mat-icon class="mat-icon-rtl-mirror">
|
||||
{{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
|
||||
</mat-icon>
|
||||
</button>
|
||||
{{node.filename}}: {{node.type}}
|
||||
<div [class.example-tree-invisible]="!nestedTreeControl.isExpanded(node)">
|
||||
<ng-container cdkTreeNodeOutlet></ng-container>
|
||||
</div>
|
||||
</cdk-nested-tree-node>
|
||||
</cdk-tree>
|
|
@ -1,129 +0,0 @@
|
|||
import {NestedTreeControl} from '@angular/cdk/tree';
|
||||
import {Component, Injectable} from '@angular/core';
|
||||
import {MatTreeNestedDataSource} from '@angular/material/tree';
|
||||
import {BehaviorSubject, of as observableOf} from 'rxjs';
|
||||
|
||||
/**
|
||||
* Json node data with nested structure. Each node has a filename and a value or a list of children
|
||||
*/
|
||||
export class FileNode {
|
||||
children: FileNode[];
|
||||
filename: string;
|
||||
type: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Json tree data in string. The data could be parsed into Json object
|
||||
*/
|
||||
const TREE_DATA = JSON.stringify({
|
||||
Applications: {
|
||||
Calendar: 'app',
|
||||
Chrome: 'app',
|
||||
Webstorm: 'app'
|
||||
},
|
||||
Documents: {
|
||||
angular: {
|
||||
src: {
|
||||
compiler: 'ts',
|
||||
core: 'ts'
|
||||
}
|
||||
},
|
||||
material2: {
|
||||
src: {
|
||||
button: 'ts',
|
||||
checkbox: 'ts',
|
||||
input: 'ts'
|
||||
}
|
||||
}
|
||||
},
|
||||
Downloads: {
|
||||
October: 'pdf',
|
||||
November: 'pdf',
|
||||
Tutorial: 'html'
|
||||
},
|
||||
Pictures: {
|
||||
'Photo Booth Library': {
|
||||
Contents: 'dir',
|
||||
Pictures: 'dir'
|
||||
},
|
||||
Sun: 'png',
|
||||
Woods: 'jpg'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* File database, it can build a tree structured Json object from string.
|
||||
* Each node in Json object represents a file or a directory. For a file, it has filename and type.
|
||||
* For a directory, it has filename and children (a list of files or directories).
|
||||
* The input will be a json object string, and the output is a list of `FileNode` with nested
|
||||
* structure.
|
||||
*/
|
||||
@Injectable()
|
||||
export class FileDatabase {
|
||||
dataChange = new BehaviorSubject<FileNode[]>([]);
|
||||
|
||||
get data(): FileNode[] { return this.dataChange.value; }
|
||||
|
||||
constructor() {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
// Parse the string to json object.
|
||||
const dataObject = JSON.parse(TREE_DATA);
|
||||
|
||||
// Build the tree nodes from Json object. The result is a list of `FileNode` with nested
|
||||
// file node as children.
|
||||
const data = this.buildFileTree(dataObject, 0);
|
||||
|
||||
// Notify the change.
|
||||
this.dataChange.next(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
|
||||
* The return value is the list of `FileNode`.
|
||||
*/
|
||||
buildFileTree(obj: object, level: number): FileNode[] {
|
||||
return Object.keys(obj).reduce<FileNode[]>((accumulator, key) => {
|
||||
const value = obj[key];
|
||||
const node = new FileNode();
|
||||
node.filename = key;
|
||||
|
||||
if (value != null) {
|
||||
if (typeof value === 'object') {
|
||||
node.children = this.buildFileTree(value, level + 1);
|
||||
} else {
|
||||
node.type = value;
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator.concat(node);
|
||||
}, []);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title Tree with nested nodes
|
||||
*/
|
||||
@Component({
|
||||
selector: 'cdk-tree-nested-example',
|
||||
templateUrl: 'cdk-tree-nested-example.html',
|
||||
styleUrls: ['cdk-tree-nested-example.css'],
|
||||
providers: [FileDatabase]
|
||||
})
|
||||
export class CdkTreeNestedExample {
|
||||
nestedTreeControl: NestedTreeControl<FileNode>;
|
||||
nestedDataSource: MatTreeNestedDataSource<FileNode>;
|
||||
|
||||
constructor(database: FileDatabase) {
|
||||
this.nestedTreeControl = new NestedTreeControl<FileNode>(this._getChildren);
|
||||
this.nestedDataSource = new MatTreeNestedDataSource();
|
||||
|
||||
database.dataChange.subscribe(data => this.nestedDataSource.data = data);
|
||||
}
|
||||
|
||||
hasNestedChild = (_: number, nodeData: FileNode) => !nodeData.type;
|
||||
|
||||
private _getChildren = (node: FileNode) => observableOf(node.children);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import {COMMA, ENTER} from '@angular/cdk/keycodes';
|
||||
import {Component, ElementRef, ViewChild} from '@angular/core';
|
||||
import {FormControl} from '@angular/forms';
|
||||
import {MatAutocompleteSelectedEvent, MatChipInputEvent} from '@angular/material';
|
||||
import {MatAutocompleteSelectedEvent, MatChipInputEvent, MatAutocomplete} from '@angular/material';
|
||||
import {Observable} from 'rxjs';
|
||||
import {map, startWith} from 'rxjs/operators';
|
||||
|
||||
|
@ -17,14 +17,15 @@ export class ChipsAutocompleteExample {
|
|||
visible = true;
|
||||
selectable = true;
|
||||
removable = true;
|
||||
addOnBlur = false;
|
||||
addOnBlur = true;
|
||||
separatorKeysCodes: number[] = [ENTER, COMMA];
|
||||
fruitCtrl = new FormControl();
|
||||
filteredFruits: Observable<string[]>;
|
||||
fruits: string[] = ['Lemon'];
|
||||
allFruits: string[] = ['Apple', 'Lemon', 'Lime', 'Orange', 'Strawberry'];
|
||||
|
||||
@ViewChild('fruitInput') fruitInput: ElementRef;
|
||||
@ViewChild('fruitInput') fruitInput: ElementRef<HTMLInputElement>;
|
||||
@ViewChild('auto') matAutocomplete: MatAutocomplete;
|
||||
|
||||
constructor() {
|
||||
this.filteredFruits = this.fruitCtrl.valueChanges.pipe(
|
||||
|
@ -33,20 +34,24 @@ export class ChipsAutocompleteExample {
|
|||
}
|
||||
|
||||
add(event: MatChipInputEvent): void {
|
||||
const input = event.input;
|
||||
const value = event.value;
|
||||
// Add fruit only when MatAutocomplete is not open
|
||||
// To make sure this does not conflict with OptionSelected Event
|
||||
if (!this.matAutocomplete.isOpen) {
|
||||
const input = event.input;
|
||||
const value = event.value;
|
||||
|
||||
// Add our fruit
|
||||
if ((value || '').trim()) {
|
||||
this.fruits.push(value.trim());
|
||||
// Add our fruit
|
||||
if ((value || '').trim()) {
|
||||
this.fruits.push(value.trim());
|
||||
}
|
||||
|
||||
// Reset the input value
|
||||
if (input) {
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
this.fruitCtrl.setValue(null);
|
||||
}
|
||||
|
||||
// Reset the input value
|
||||
if (input) {
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
this.fruitCtrl.setValue(null);
|
||||
}
|
||||
|
||||
remove(fruit: string): void {
|
||||
|
|
|
@ -1,16 +1 @@
|
|||
.example-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.example-header-label {
|
||||
flex: 1;
|
||||
height: 1em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.example-double-arrow .mat-icon {
|
||||
margin: -22%;
|
||||
}
|
||||
/** No CSS for this example */
|
||||
|
|
|
@ -15,7 +15,6 @@ import {takeUntil} from 'rxjs/operators';
|
|||
@Component({
|
||||
selector: 'datepicker-custom-header-example',
|
||||
templateUrl: 'datepicker-custom-header-example.html',
|
||||
styleUrls: ['datepicker-custom-header-example.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DatepickerCustomHeaderExample {
|
||||
|
@ -25,6 +24,24 @@ export class DatepickerCustomHeaderExample {
|
|||
/** Custom header component for datepicker. */
|
||||
@Component({
|
||||
selector: 'example-header',
|
||||
styles: [`
|
||||
.example-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.example-header-label {
|
||||
flex: 1;
|
||||
height: 1em;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.example-double-arrow .mat-icon {
|
||||
margin: -22%;
|
||||
}
|
||||
`],
|
||||
template: `
|
||||
<div class="example-header">
|
||||
<button mat-icon-button class="example-double-arrow" (click)="previousClicked('year')">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.example-headers-align .mat-expansion-panel-header-title,
|
||||
.example-headers-align .mat-expansion-panel-header-title,
|
||||
.example-headers-align .mat-expansion-panel-header-description {
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
styleUrls: ['focus-monitor-focus-via-example.css']
|
||||
})
|
||||
export class FocusMonitorFocusViaExample implements OnDestroy, OnInit {
|
||||
@ViewChild('monitored') monitoredEl: ElementRef;
|
||||
@ViewChild('monitored') monitoredEl: ElementRef<HTMLElement>;
|
||||
|
||||
origin = this.formatOrigin(null);
|
||||
|
||||
|
@ -25,7 +25,7 @@ export class FocusMonitorFocusViaExample implements OnDestroy, OnInit {
|
|||
private ngZone: NgZone) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.focusMonitor.monitor(this.monitoredEl.nativeElement)
|
||||
this.focusMonitor.monitor(this.monitoredEl)
|
||||
.subscribe(origin => this.ngZone.run(() => {
|
||||
this.origin = this.formatOrigin(origin);
|
||||
this.cdr.markForCheck();
|
||||
|
@ -33,7 +33,7 @@ export class FocusMonitorFocusViaExample implements OnDestroy, OnInit {
|
|||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.focusMonitor.stopMonitoring(this.monitoredEl.nativeElement);
|
||||
this.focusMonitor.stopMonitoring(this.monitoredEl);
|
||||
}
|
||||
|
||||
formatOrigin(origin: FocusOrigin): string {
|
||||
|
|
|
@ -16,8 +16,8 @@ import {
|
|||
styleUrls: ['focus-monitor-overview-example.css']
|
||||
})
|
||||
export class FocusMonitorOverviewExample implements OnDestroy, OnInit {
|
||||
@ViewChild('element') element: ElementRef;
|
||||
@ViewChild('subtree') subtree: ElementRef;
|
||||
@ViewChild('element') element: ElementRef<HTMLElement>;
|
||||
@ViewChild('subtree') subtree: ElementRef<HTMLElement>;
|
||||
|
||||
elementOrigin = this.formatOrigin(null);
|
||||
subtreeOrigin = this.formatOrigin(null);
|
||||
|
@ -27,12 +27,12 @@ export class FocusMonitorOverviewExample implements OnDestroy, OnInit {
|
|||
private ngZone: NgZone) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.focusMonitor.monitor(this.element.nativeElement)
|
||||
this.focusMonitor.monitor(this.element)
|
||||
.subscribe(origin => this.ngZone.run(() => {
|
||||
this.elementOrigin = this.formatOrigin(origin);
|
||||
this.cdr.markForCheck();
|
||||
}));
|
||||
this.focusMonitor.monitor(this.subtree.nativeElement, true)
|
||||
this.focusMonitor.monitor(this.subtree, true)
|
||||
.subscribe(origin => this.ngZone.run(() => {
|
||||
this.subtreeOrigin = this.formatOrigin(origin);
|
||||
this.cdr.markForCheck();
|
||||
|
@ -40,8 +40,8 @@ export class FocusMonitorOverviewExample implements OnDestroy, OnInit {
|
|||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.focusMonitor.stopMonitoring(this.element.nativeElement);
|
||||
this.focusMonitor.stopMonitoring(this.subtree.nativeElement);
|
||||
this.focusMonitor.stopMonitoring(this.element);
|
||||
this.focusMonitor.stopMonitoring(this.subtree);
|
||||
}
|
||||
|
||||
formatOrigin(origin: FocusOrigin): string {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
.example-tel-input-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.example-tel-input-element {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
font: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.example-tel-input-spacer {
|
||||
opacity: 0;
|
||||
transition: opacity 200ms;
|
||||
}
|
||||
|
||||
:host.example-floating .example-tel-input-spacer {
|
||||
opacity: 1;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<div [formGroup]="parts" class="example-tel-input-container">
|
||||
<input class="example-tel-input-element" formControlName="area" size="3">
|
||||
<span class="example-tel-input-spacer">–</span>
|
||||
<input class="example-tel-input-element" formControlName="exchange" size="3">
|
||||
<span class="example-tel-input-spacer">–</span>
|
||||
<input class="example-tel-input-element" formControlName="subscriber" size="4">
|
||||
</div>
|
|
@ -1,21 +1 @@
|
|||
div {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
input {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
font: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span {
|
||||
opacity: 0;
|
||||
transition: opacity 200ms;
|
||||
}
|
||||
|
||||
:host.floating span {
|
||||
opacity: 1;
|
||||
}
|
||||
/** No CSS for this example */
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
<div [formGroup]="parts">
|
||||
<input class="area" formControlName="area" size="3">
|
||||
<span>–</span>
|
||||
<input class="exchange" formControlName="exchange" size="3">
|
||||
<span>–</span>
|
||||
<input class="subscriber" formControlName="subscriber" size="4">
|
||||
</div>
|
||||
<mat-form-field>
|
||||
<example-tel-input placeholder="Phone number" required></example-tel-input>
|
||||
<mat-icon matSuffix>phone</mat-icon>
|
||||
<mat-hint>Include area code</mat-hint>
|
||||
</mat-form-field>
|
||||
|
|
|
@ -5,20 +5,27 @@ import {FormBuilder, FormGroup} from '@angular/forms';
|
|||
import {MatFormFieldControl} from '@angular/material';
|
||||
import {Subject} from 'rxjs';
|
||||
|
||||
/** @title Form field with custom telephone number input control. */
|
||||
@Component({
|
||||
selector: 'form-field-custom-control-example',
|
||||
templateUrl: 'form-field-custom-control-example.html',
|
||||
styleUrls: ['form-field-custom-control-example.css'],
|
||||
})
|
||||
export class FormFieldCustomControlExample {}
|
||||
|
||||
/** Data structure for holding telephone number. */
|
||||
export class MyTel {
|
||||
constructor(public area: string, public exchange: string, public subscriber: string) {}
|
||||
}
|
||||
|
||||
|
||||
/** Custom `MatFormFieldControl` for telephone number input. */
|
||||
@Component({
|
||||
selector: 'my-tel-input',
|
||||
templateUrl: 'form-field-custom-control-example.html',
|
||||
styleUrls: ['form-field-custom-control-example.css'],
|
||||
selector: 'example-tel-input',
|
||||
templateUrl: 'example-tel-input-example.html',
|
||||
styleUrls: ['example-tel-input-example.css'],
|
||||
providers: [{provide: MatFormFieldControl, useExisting: MyTelInput}],
|
||||
host: {
|
||||
'[class.floating]': 'shouldLabelFloat',
|
||||
'[class.example-floating]': 'shouldLabelFloat',
|
||||
'[id]': 'id',
|
||||
'[attr.aria-describedby]': 'describedBy',
|
||||
}
|
||||
|
@ -31,8 +38,8 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
|
|||
focused = false;
|
||||
ngControl = null;
|
||||
errorState = false;
|
||||
controlType = 'my-tel-input';
|
||||
id = `my-tel-input-${MyTelInput.nextId++}`;
|
||||
controlType = 'example-tel-input';
|
||||
id = `example-tel-input-${MyTelInput.nextId++}`;
|
||||
describedBy = '';
|
||||
|
||||
get empty() {
|
||||
|
@ -81,14 +88,14 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
|
|||
this.stateChanges.next();
|
||||
}
|
||||
|
||||
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef) {
|
||||
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>) {
|
||||
this.parts = fb.group({
|
||||
area: '',
|
||||
exchange: '',
|
||||
subscriber: '',
|
||||
});
|
||||
|
||||
fm.monitor(elRef.nativeElement, true).subscribe(origin => {
|
||||
fm.monitor(elRef, true).subscribe(origin => {
|
||||
this.focused = !!origin;
|
||||
this.stateChanges.next();
|
||||
});
|
||||
|
@ -96,7 +103,7 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
|
|||
|
||||
ngOnDestroy() {
|
||||
this.stateChanges.complete();
|
||||
this.fm.stopMonitoring(this.elRef.nativeElement);
|
||||
this.fm.stopMonitoring(this.elRef);
|
||||
}
|
||||
|
||||
setDescribedByIds(ids: string[]) {
|
||||
|
@ -105,21 +112,7 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
|
|||
|
||||
onContainerClick(event: MouseEvent) {
|
||||
if ((event.target as Element).tagName.toLowerCase() != 'input') {
|
||||
this.elRef.nativeElement.querySelector('input').focus();
|
||||
this.elRef.nativeElement.querySelector('input')!.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @title Form field with custom telephone number input control. */
|
||||
@Component({
|
||||
selector: 'form-field-custom-control-example',
|
||||
template: `
|
||||
<mat-form-field>
|
||||
<my-tel-input placeholder="Phone number" required></my-tel-input>
|
||||
<mat-icon matSuffix>phone</mat-icon>
|
||||
<mat-hint>Include area code</mat-hint>
|
||||
</mat-form-field>
|
||||
`
|
||||
})
|
||||
export class FormFieldCustomControlExample {}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="example-container">
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Enter your password" [type]="hide ? 'password' : 'text'">
|
||||
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 'visibility_off'}}</mat-icon>
|
||||
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
.example-ripple-container {
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
line-height: 300px;
|
||||
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
|
||||
-webkit-user-drag: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
/** Styles to make the demo look better. */
|
||||
.example-ripple-checkbox {
|
||||
margin: 6px 12px 6px 0;
|
||||
}
|
||||
|
||||
.example-ripple-form-field {
|
||||
margin: 0 12px 0 0;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<mat-checkbox [(ngModel)]="centered" class="example-ripple-checkbox">Centered</mat-checkbox>
|
||||
<mat-checkbox [(ngModel)]="disabled" class="example-ripple-checkbox">Disabled</mat-checkbox>
|
||||
<mat-checkbox [(ngModel)]="unbounded" class="example-ripple-checkbox">Unbounded</mat-checkbox>
|
||||
|
||||
<mat-form-field class="example-ripple-form-field">
|
||||
<input matInput [(ngModel)]="radius" type="number" placeholder="Radius">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="example-ripple-form-field">
|
||||
<input matInput [(ngModel)]="color" type="text" placeholder="Color">
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<div class="example-ripple-container mat-elevation-z4"
|
||||
matRipple
|
||||
[matRippleCentered]="centered"
|
||||
[matRippleDisabled]="disabled"
|
||||
[matRippleUnbounded]="unbounded"
|
||||
[matRippleRadius]="radius"
|
||||
[matRippleColor]="color">
|
||||
Click me
|
||||
</div>
|
|
@ -0,0 +1,18 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
/**
|
||||
* @title MatRipple basic usage
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ripple-overview-example',
|
||||
templateUrl: 'ripple-overview-example.html',
|
||||
styleUrls: ['ripple-overview-example.css'],
|
||||
})
|
||||
export class RippleOverviewExample {
|
||||
centered = false;
|
||||
disabled = false;
|
||||
unbounded = false;
|
||||
|
||||
radius: number;
|
||||
color: string;
|
||||
}
|
|
@ -1,12 +1,24 @@
|
|||
<p>
|
||||
<mat-checkbox [formControl]="disableSelect">Disable select</mat-checkbox>
|
||||
</p>
|
||||
<p>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Choose an option" [disabled]="disableSelect.value">
|
||||
<mat-option value="option1">Option 1</mat-option>
|
||||
<mat-option value="option2" disabled>Option 2 (disabled)</mat-option>
|
||||
<mat-option value="option3">Option 3</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</p>
|
||||
|
||||
<h4>mat-select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Choose an option" [disabled]="disableSelect.value">
|
||||
<mat-option value="option1">Option 1</mat-option>
|
||||
<mat-option value="option2" disabled>Option 2 (disabled)</mat-option>
|
||||
<mat-option value="option3">Option 3</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<h4>native html select</h4>
|
||||
<mat-form-field>
|
||||
<select matNativeControl placeholder="Choose an option" [disabled]="disableSelect.value">
|
||||
<option value="" disabled selected></option>
|
||||
<option value="volvo">Volvo</option>
|
||||
<option value="saab" disabled>Saab</option>
|
||||
<option value="mercedes">Mercedes</option>
|
||||
<option value="audi">Audi</option>
|
||||
</select>
|
||||
</mat-form-field>
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<h4>mat-select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Choose one" [formControl]="selected" [errorStateMatcher]="matcher">
|
||||
<mat-option>Clear</mat-option>
|
||||
|
@ -10,3 +11,16 @@
|
|||
Your selection is invalid
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<h4>native html select</h4>
|
||||
<mat-form-field class="demo-full-width">
|
||||
<select matNativeControl placeholder="Choose one" [formControl]="nativeSelectFormControl" [errorStateMatcher]="matcher">
|
||||
<option value=""></option>
|
||||
<option value="valid" selected>Valid option</option>
|
||||
<option value="invalid">Invalid option</option>
|
||||
</select>
|
||||
<mat-error *ngIf="nativeSelectFormControl.hasError('required')">You must make a selection</mat-error>
|
||||
<mat-error *ngIf="nativeSelectFormControl.hasError('pattern') && !nativeSelectFormControl.hasError('required')">
|
||||
Your selection is invalid
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
|
|
@ -22,5 +22,15 @@ export class SelectErrorStateMatcherExample {
|
|||
Validators.pattern('valid'),
|
||||
]);
|
||||
|
||||
selectFormControl = new FormControl('valid', [
|
||||
Validators.required,
|
||||
Validators.pattern('valid'),
|
||||
]);
|
||||
|
||||
nativeSelectFormControl = new FormControl('valid', [
|
||||
Validators.required,
|
||||
Validators.pattern('valid'),
|
||||
]);
|
||||
|
||||
matcher = new MyErrorStateMatcher();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<form>
|
||||
<h4>mat-select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Favorite food" [(ngModel)]="selectedValue" name="food">
|
||||
<mat-option *ngFor="let food of foods" [value]="food.value">
|
||||
|
@ -6,6 +7,15 @@
|
|||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<p> Selected value: {{selectedValue}} </p>
|
||||
<p> Selected food: {{selectedValue}} </p>
|
||||
<h4>native html select</h4>
|
||||
<mat-form-field>
|
||||
<select matNativeControl placeholder="Favorite car" [(ngModel)]="selectedCar" name="car">
|
||||
<option value="" disabled selected></option>
|
||||
<option *ngFor="let car of cars" [value]="car.value">
|
||||
{{car.viewValue}}
|
||||
</option>
|
||||
</select>
|
||||
</mat-form-field>
|
||||
<p> Selected car: {{selectedCar}} </p>
|
||||
</form>
|
||||
|
|
|
@ -5,6 +5,11 @@ export interface Food {
|
|||
viewValue: string;
|
||||
}
|
||||
|
||||
export interface Car {
|
||||
value: string;
|
||||
viewValue: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @title Select in a form
|
||||
*/
|
||||
|
@ -15,10 +20,17 @@ export interface Food {
|
|||
})
|
||||
export class SelectFormExample {
|
||||
selectedValue: string;
|
||||
selectedCar: string;
|
||||
|
||||
foods: Food[] = [
|
||||
{value: 'steak-0', viewValue: 'Steak'},
|
||||
{value: 'pizza-1', viewValue: 'Pizza'},
|
||||
{value: 'tacos-2', viewValue: 'Tacos'}
|
||||
];
|
||||
|
||||
cars: Car[] = [
|
||||
{value: 'volvo', viewValue: 'Volvo'},
|
||||
{value: 'saab', viewValue: 'Saab'},
|
||||
{value: 'mercedes', viewValue: 'Mercedes'}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<h4>mat select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Favorite animal" [formControl]="animalControl" required>
|
||||
<mat-option>--</mat-option>
|
||||
|
@ -8,3 +9,19 @@
|
|||
<mat-error *ngIf="animalControl.hasError('required')">Please choose an animal</mat-error>
|
||||
<mat-hint>{{animalControl.value?.sound}}</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<h4>native html select</h4>
|
||||
<mat-form-field>
|
||||
<mat-label>Select your car (required)</mat-label>
|
||||
<select matNativeControl required [formControl]="selectFormControl">
|
||||
<option label="--select something --"></option>
|
||||
<option value="saab">Saab</option>
|
||||
<option value="mercedes">Mercedes</option>
|
||||
<option value="audi">Audi</option>
|
||||
</select>
|
||||
<mat-error *ngIf="selectFormControl.hasError('required')">
|
||||
This field is required
|
||||
</mat-error>
|
||||
<mat-hint>You can pick up your favorite car here</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ export interface Animal {
|
|||
})
|
||||
export class SelectHintErrorExample {
|
||||
animalControl = new FormControl('', [Validators.required]);
|
||||
selectFormControl = new FormControl('', Validators.required);
|
||||
animals: Animal[] = [
|
||||
{name: 'Dog', sound: 'Woof!'},
|
||||
{name: 'Cat', sound: 'Meow!'},
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<h4>mat-select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Pokemon" [formControl]="pokemonControl">
|
||||
<mat-option>-- None --</mat-option>
|
||||
|
@ -9,3 +10,17 @@
|
|||
</mat-optgroup>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<h4>native html select</h4>
|
||||
<mat-form-field>
|
||||
<select matNativeControl>
|
||||
<optgroup label="Swedish Cars">
|
||||
<option value="volvo">volvo</option>
|
||||
<option value="saab">Saab</option>
|
||||
</optgroup>
|
||||
<optgroup label="German Cars">
|
||||
<option value="mercedes">Mercedes</option>
|
||||
<option value="audi">Audi</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</mat-form-field>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<h4>Basic mat-select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Favorite food">
|
||||
<mat-option *ngFor="let food of foods" [value]="food.value">
|
||||
|
@ -5,3 +6,13 @@
|
|||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<h4>Basic native select</h4>
|
||||
<mat-form-field>
|
||||
<select matNativeControl required>
|
||||
<option value="volvo">Volvo</option>
|
||||
<option value="saab">Saab</option>
|
||||
<option value="mercedes">Mercedes</option>
|
||||
<option value="audi">Audi</option>
|
||||
</select>
|
||||
</mat-form-field>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
.example-panel-red .mat-select-content {
|
||||
.example-panel-red .mat-select-panel {
|
||||
background: rgba(255, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.example-panel-green .mat-select-content {
|
||||
.example-panel-green .mat-select-panel {
|
||||
background: rgba(0, 255, 0, 0.5);
|
||||
}
|
||||
|
||||
.example-panel-blue .mat-select-content {
|
||||
.example-panel-blue .mat-select-panel {
|
||||
background: rgba(0, 0, 255, 0.5);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
<h4>mat-select</h4>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="State">
|
||||
<mat-option>None</mat-option>
|
||||
<mat-option *ngFor="let state of states" [value]="state">{{state}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<h4>native html select</h4>
|
||||
<mat-form-field>
|
||||
<mat-label>Select your car</mat-label>
|
||||
<select matNativeControl id="mySelectId">
|
||||
<option value="" disabled selected></option>
|
||||
<option value="volvo">Volvo</option>
|
||||
<option value="saab">Saab</option>
|
||||
<option value="mercedes">Mercedes</option>
|
||||
<option value="audi">Audi</option>
|
||||
</select>
|
||||
</mat-form-field>
|
||||
|
|
|
@ -53,6 +53,6 @@ export class SortOverviewExample {
|
|||
}
|
||||
}
|
||||
|
||||
function compare(a, b, isAsc) {
|
||||
function compare(a: number | string, b: number | string, isAsc: boolean) {
|
||||
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<mat-horizontal-stepper linear #stepper>
|
||||
<mat-step [stepControl]="firstFormGroup" errorMessage="Name is required.">
|
||||
<form [formGroup]="firstFormGroup">
|
||||
<ng-template matStepLabel>Fill out your name</ng-template>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="secondFormGroup" errorMessage="Address is required.">
|
||||
<form [formGroup]="secondFormGroup">
|
||||
<ng-template matStepLabel>Fill out your address</ng-template>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Address" formControlName="secondCtrl" required>
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>Done</ng-template>
|
||||
You are now done.
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button (click)="stepper.reset()">Reset</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
|
@ -0,0 +1,30 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
||||
import {MAT_STEPPER_GLOBAL_OPTIONS} from '@angular/cdk/stepper';
|
||||
|
||||
/**
|
||||
* @title Stepper that displays errors in the steps
|
||||
*/
|
||||
@Component({
|
||||
selector: 'stepper-errors-example',
|
||||
templateUrl: 'stepper-errors-example.html',
|
||||
styleUrls: ['stepper-errors-example.css'],
|
||||
providers: [{
|
||||
provide: MAT_STEPPER_GLOBAL_OPTIONS, useValue: {showError: true}
|
||||
}]
|
||||
})
|
||||
export class StepperErrorsExample implements OnInit {
|
||||
firstFormGroup: FormGroup;
|
||||
secondFormGroup: FormGroup;
|
||||
|
||||
constructor(private _formBuilder: FormBuilder) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.firstFormGroup = this._formBuilder.group({
|
||||
firstCtrl: ['', Validators.required]
|
||||
});
|
||||
this.secondFormGroup = this._formBuilder.group({
|
||||
secondCtrl: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/** No CSS for this example */
|
|
@ -0,0 +1,33 @@
|
|||
<mat-horizontal-stepper labelPosition="bottom" #stepper>
|
||||
<mat-step [stepControl]="firstFormGroup">
|
||||
<form [formGroup]="firstFormGroup">
|
||||
<ng-template matStepLabel>Fill out your name</ng-template>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="secondFormGroup" optional>
|
||||
<form [formGroup]="secondFormGroup">
|
||||
<ng-template matStepLabel>Fill out your address</ng-template>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Address" formControlName="secondCtrl" required>
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>Done</ng-template>
|
||||
You are now done.
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button (click)="stepper.reset()">Reset</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
|
@ -0,0 +1,26 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
||||
|
||||
/**
|
||||
* @title Stepper label bottom position
|
||||
*/
|
||||
@Component({
|
||||
selector: 'stepper-label-position-bottom-example',
|
||||
templateUrl: 'stepper-label-position-bottom-example.html',
|
||||
styleUrls: ['stepper-label-position-bottom-example.css'],
|
||||
})
|
||||
export class StepperLabelPositionBottomExample implements OnInit {
|
||||
firstFormGroup: FormGroup;
|
||||
secondFormGroup: FormGroup;
|
||||
|
||||
constructor(private _formBuilder: FormBuilder) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.firstFormGroup = this._formBuilder.group({
|
||||
firstCtrl: ['', Validators.required]
|
||||
});
|
||||
this.secondFormGroup = this._formBuilder.group({
|
||||
secondCtrl: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<mat-horizontal-stepper #stepper>
|
||||
<mat-step [stepControl]="firstFormGroup">
|
||||
<form [formGroup]="firstFormGroup">
|
||||
<ng-template matStepLabel>Fill out your name</ng-template>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step [stepControl]="secondFormGroup">
|
||||
<form [formGroup]="secondFormGroup">
|
||||
<ng-template matStepLabel>Fill out your address</ng-template>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Address" formControlName="secondCtrl" required>
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>Done</ng-template>
|
||||
You are now done.
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button (click)="stepper.reset()">Reset</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
</mat-horizontal-stepper>
|
||||
|
||||
<mat-horizontal-stepper>
|
||||
<mat-step label="Step 1" state="phone">
|
||||
<p>Put down your phones.</p>
|
||||
<div>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
<mat-step label="Step 2" state="chat">
|
||||
<p>Socialize with each other.</p>
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>Back</button>
|
||||
<button mat-button matStepperNext>Next</button>
|
||||
</div>
|
||||
</mat-step>
|
||||
<mat-step label="Step 3">
|
||||
<p>You're welcome.</p>
|
||||
</mat-step>
|
||||
|
||||
<!-- Icon overrides. -->
|
||||
<ng-template matStepperIcon="phone">
|
||||
<mat-icon>call_end</mat-icon>
|
||||
</ng-template>
|
||||
<ng-template matStepperIcon="chat">
|
||||
<mat-icon>forum</mat-icon>
|
||||
</ng-template>
|
||||
</mat-horizontal-stepper>
|
|
@ -0,0 +1,30 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
||||
import {MAT_STEPPER_GLOBAL_OPTIONS} from '@angular/cdk/stepper';
|
||||
|
||||
/**
|
||||
* @title Stepper with customized states
|
||||
*/
|
||||
@Component({
|
||||
selector: 'stepper-states-example',
|
||||
templateUrl: 'stepper-states-example.html',
|
||||
styleUrls: ['stepper-states-example.css'],
|
||||
providers: [{
|
||||
provide: MAT_STEPPER_GLOBAL_OPTIONS, useValue: {displayDefaultIndicatorType: false}
|
||||
}]
|
||||
})
|
||||
export class StepperStatesExample implements OnInit {
|
||||
firstFormGroup: FormGroup;
|
||||
secondFormGroup: FormGroup;
|
||||
|
||||
constructor(private _formBuilder: FormBuilder) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.firstFormGroup = this._formBuilder.group({
|
||||
firstCtrl: ['', Validators.required]
|
||||
});
|
||||
this.secondFormGroup = this._formBuilder.group({
|
||||
secondCtrl: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
|||
* @title Stepper vertical
|
||||
*/
|
||||
@Component({
|
||||
selector: 'stepper-vertical',
|
||||
selector: 'stepper-vertical-example',
|
||||
templateUrl: 'stepper-vertical-example.html',
|
||||
styleUrls: ['stepper-vertical-example.css']
|
||||
})
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.mat-tab-group {
|
||||
margin-bottom: 48px;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<mat-tab-group mat-align-tabs="start">
|
||||
<mat-tab label="First">Content 1</mat-tab>
|
||||
<mat-tab label="Second">Content 2</mat-tab>
|
||||
<mat-tab label="Third">Content 3</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<mat-tab-group mat-align-tabs="center">
|
||||
<mat-tab label="First">Content 1</mat-tab>
|
||||
<mat-tab label="Second">Content 2</mat-tab>
|
||||
<mat-tab label="Third">Content 3</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<mat-tab-group mat-align-tabs="end">
|
||||
<mat-tab label="First">Content 1</mat-tab>
|
||||
<mat-tab label="Second">Content 2</mat-tab>
|
||||
<mat-tab label="Third">Content 3</mat-tab>
|
||||
</mat-tab-group>
|
|
@ -0,0 +1,11 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
/**
|
||||
* @title Tab group with aligned labels
|
||||
*/
|
||||
@Component({
|
||||
selector: 'tab-group-align-example',
|
||||
templateUrl: 'tab-group-align-example.html',
|
||||
styleUrls: ['tab-group-align-example.css'],
|
||||
})
|
||||
export class TabGroupAlignExample {}
|
|
@ -0,0 +1,3 @@
|
|||
table {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8"
|
||||
matSort #sort="matSort">
|
||||
<!-- Basic column: name is used for header label AND data property -->
|
||||
<simple-column name="name" sortable></simple-column>
|
||||
<simple-column name="position"></simple-column>
|
||||
|
||||
<!-- Name doesn't match the data property (or transform needed); define a custom data accessor -->
|
||||
<simple-column name="weight" [dataAccessor]="getWeight"></simple-column>
|
||||
|
||||
<!-- Name doesn't match desired header text; define a custom label -->
|
||||
<simple-column name="symbol" label="SYMBOL!"></simple-column>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let data; columns: displayedColumns;"></tr>
|
||||
</table>
|
|
@ -0,0 +1,130 @@
|
|||
import {Component, Input, OnDestroy, OnInit, Optional, ViewChild} from '@angular/core';
|
||||
import {coerceBooleanProperty} from '@angular/cdk/coercion';
|
||||
import {
|
||||
MatColumnDef,
|
||||
MatSort,
|
||||
MatSortHeader,
|
||||
MatTable,
|
||||
MatTableDataSource
|
||||
} from '@angular/material';
|
||||
|
||||
export interface PeriodicElement {
|
||||
name: string;
|
||||
position: number;
|
||||
weight: number;
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
const ELEMENT_DATA: PeriodicElement[] = [
|
||||
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
|
||||
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
|
||||
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
|
||||
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
|
||||
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
|
||||
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
|
||||
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
|
||||
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
|
||||
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
|
||||
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
|
||||
];
|
||||
|
||||
/**
|
||||
* @title Table with a custom column component for easy column definition reuse.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'table-simple-column-example',
|
||||
styleUrls: ['table-simple-column-example.css'],
|
||||
templateUrl: 'table-simple-column-example.html',
|
||||
})
|
||||
export class TableSimpleColumnExample implements OnInit {
|
||||
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
|
||||
dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
|
||||
getWeight = (data: PeriodicElement) => '~' + data.weight;
|
||||
|
||||
@ViewChild('sort') sort: MatSort;
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Column that shows simply shows text content for the header and row
|
||||
* cells. By default, the name of this column will be assumed to be both the header
|
||||
* text and data property used to access the data value to show in cells. To override
|
||||
* the header text, provide a label text. To override the data cell values,
|
||||
* provide a dataAccessor function that provides the string to display for each row's cell.
|
||||
*
|
||||
* Note that this component sets itself as visually hidden since it will show up in the `mat-table`
|
||||
* DOM because it is an empty element with an ng-container (nothing rendered). It should not
|
||||
* interfere with screen readers.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'simple-column',
|
||||
template: `
|
||||
<ng-container matColumnDef>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{label || name}} </th>
|
||||
<td mat-cell *matCellDef="let data"> {{getData(data)}}</td>
|
||||
</ng-container>
|
||||
`,
|
||||
host: {
|
||||
'class': 'simple-column cdk-visually-hidden',
|
||||
'[attr.ariaHidden]': 'true',
|
||||
}
|
||||
})
|
||||
export class SimpleColumn<T> implements OnDestroy, OnInit {
|
||||
/** Column name that should be used to reference this column. */
|
||||
@Input()
|
||||
get name(): string { return this._name; }
|
||||
set name(name: string) {
|
||||
this._name = name;
|
||||
this.columnDef.name = name;
|
||||
}
|
||||
_name: string;
|
||||
|
||||
/**
|
||||
* Text label that should be used for the column header. If this property is not
|
||||
* set, the header text will default to the column name.
|
||||
*/
|
||||
@Input() label: string;
|
||||
|
||||
/**
|
||||
* Accessor function to retrieve the data should be provided to the cell. If this
|
||||
* property is not set, the data cells will assume that the column name is the same
|
||||
* as the data property the cells should display.
|
||||
*/
|
||||
@Input() dataAccessor: ((data: T, name: string) => string);
|
||||
|
||||
/** Alignment of the cell values. */
|
||||
@Input() align: 'before' | 'after' = 'before';
|
||||
|
||||
/** Whether the column is sortable */
|
||||
@Input()
|
||||
get sortable(): boolean { return this._sortable; }
|
||||
set sortable(sortable: boolean) {
|
||||
this._sortable = coerceBooleanProperty(sortable);
|
||||
}
|
||||
_sortable: boolean;
|
||||
|
||||
@ViewChild(MatColumnDef) columnDef: MatColumnDef;
|
||||
|
||||
@ViewChild(MatSortHeader) sortHeader: MatSortHeader;
|
||||
|
||||
constructor(@Optional() public table: MatTable<any>) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (this.table) {
|
||||
this.table.addColumnDef(this.columnDef);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.table) {
|
||||
this.table.removeColumnDef(this.columnDef);
|
||||
}
|
||||
}
|
||||
|
||||
getData(data: T): any {
|
||||
return this.dataAccessor ? this.dataAccessor(data, this.name) : (data as any)[this.name];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
table {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<wrapper-table [dataSource]="dataSource" [columns]="displayedColumns"
|
||||
matSort #sort="matSort">
|
||||
<!-- Custom column definition to be provided to the wrapper table. -->
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Custom row definitions to be provided to the wrapper table. -->
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns; "></tr>
|
||||
</wrapper-table>
|
88
src/assets/angular-material-examples/table-wrapped/table-wrapped-example.ts
Executable file
88
src/assets/angular-material-examples/table-wrapped/table-wrapped-example.ts
Executable file
|
@ -0,0 +1,88 @@
|
|||
import {
|
||||
AfterContentInit,
|
||||
Component,
|
||||
ContentChildren,
|
||||
Input,
|
||||
OnInit,
|
||||
QueryList,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import {
|
||||
MatColumnDef,
|
||||
MatHeaderRowDef,
|
||||
MatRowDef,
|
||||
MatSort,
|
||||
MatTable,
|
||||
MatTableDataSource
|
||||
} from '@angular/material';
|
||||
import {DataSource} from '@angular/cdk/collections';
|
||||
|
||||
export interface PeriodicElement {
|
||||
name: string;
|
||||
position: number;
|
||||
weight: number;
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
const ELEMENT_DATA: PeriodicElement[] = [
|
||||
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
|
||||
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
|
||||
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
|
||||
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
|
||||
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
|
||||
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
|
||||
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
|
||||
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
|
||||
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
|
||||
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
|
||||
];
|
||||
|
||||
/**
|
||||
* @title Table example that shows how to wrap a table component for definition and behavior reuse.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'table-wrapped-example',
|
||||
styleUrls: ['table-wrapped-example.css'],
|
||||
templateUrl: 'table-wrapped-example.html',
|
||||
})
|
||||
export class TableWrappedExample implements OnInit {
|
||||
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
|
||||
dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
|
||||
|
||||
@ViewChild('sort') sort: MatSort;
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table component that accepts column and row definitions in its content to be registered to the
|
||||
* table.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'wrapper-table',
|
||||
templateUrl: 'wrapper-table.html',
|
||||
styles: [`
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class WrapperTable<T> implements AfterContentInit {
|
||||
@ContentChildren(MatHeaderRowDef) headerRowDefs: QueryList<MatHeaderRowDef>;
|
||||
@ContentChildren(MatRowDef) rowDefs: QueryList<MatRowDef<T>>;
|
||||
@ContentChildren(MatColumnDef) columnDefs: QueryList<MatColumnDef>;
|
||||
|
||||
@ViewChild(MatTable) table: MatTable<T>;
|
||||
|
||||
@Input() columns: string[];
|
||||
|
||||
@Input() dataSource: DataSource<T>;
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.columnDefs.forEach(columnDef => this.table.addColumnDef(columnDef));
|
||||
this.rowDefs.forEach(rowDef => this.table.addRowDef(rowDef));
|
||||
this.headerRowDefs.forEach(headerRowDef => this.table.addHeaderRowDef(headerRowDef));
|
||||
}
|
||||
}
|
21
src/assets/angular-material-examples/table-wrapped/wrapper-table.html
Executable file
21
src/assets/angular-material-examples/table-wrapped/wrapper-table.html
Executable file
|
@ -0,0 +1,21 @@
|
|||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
<ng-content></ng-content>
|
||||
|
||||
<!-- Position Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Color Column -->
|
||||
<ng-container matColumnDef="symbol">
|
||||
<th mat-header-cell *matHeaderCellDef> Symbol </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
</table>
|
|
@ -8,22 +8,22 @@ import {Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core
|
|||
styleUrls: ['./text-field-autofill-monitor-example.css'],
|
||||
})
|
||||
export class TextFieldAutofillMonitorExample implements OnDestroy, OnInit {
|
||||
@ViewChild('first', {read: ElementRef}) firstName: ElementRef;
|
||||
@ViewChild('last', {read: ElementRef}) lastName: ElementRef;
|
||||
@ViewChild('first', {read: ElementRef}) firstName: ElementRef<HTMLElement>;
|
||||
@ViewChild('last', {read: ElementRef}) lastName: ElementRef<HTMLElement>;
|
||||
firstNameAutofilled: boolean;
|
||||
lastNameAutofilled: boolean;
|
||||
|
||||
constructor(private autofill: AutofillMonitor) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.autofill.monitor(this.firstName.nativeElement)
|
||||
this.autofill.monitor(this.firstName)
|
||||
.subscribe(e => this.firstNameAutofilled = e.isAutofilled);
|
||||
this.autofill.monitor(this.lastName.nativeElement)
|
||||
this.autofill.monitor(this.lastName)
|
||||
.subscribe(e => this.lastNameAutofilled = e.isAutofilled);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.autofill.stopMonitoring(this.firstName.nativeElement);
|
||||
this.autofill.stopMonitoring(this.lastName.nativeElement);
|
||||
this.autofill.stopMonitoring(this.firstName);
|
||||
this.autofill.stopMonitoring(this.lastName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
.example-button {
|
||||
display: block;
|
||||
width: 48px;
|
||||
margin: 80px auto 400px;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<button mat-icon-button disabled></button>
|
||||
<mat-checkbox class="checklist-leaf-node"
|
||||
[checked]="checklistSelection.isSelected(node)"
|
||||
(change)="checklistSelection.toggle(node);">{{node.item}}</mat-checkbox>
|
||||
(change)="todoLeafItemSelectionToggle(node)">{{node.item}}</mat-checkbox>
|
||||
</mat-tree-node>
|
||||
|
||||
<mat-tree-node *matTreeNodeDef="let node; when: hasNoContent" matTreeNodePadding>
|
||||
|
|
|
@ -68,7 +68,7 @@ export class ChecklistDatabase {
|
|||
* Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
|
||||
* The return value is the list of `TodoItemNode`.
|
||||
*/
|
||||
buildFileTree(obj: object, level: number): TodoItemNode[] {
|
||||
buildFileTree(obj: {[key: string]: any}, level: number): TodoItemNode[] {
|
||||
return Object.keys(obj).reduce<TodoItemNode[]>((accumulator, key) => {
|
||||
const value = obj[key];
|
||||
const node = new TodoItemNode();
|
||||
|
@ -168,10 +168,13 @@ export class TreeChecklistExample {
|
|||
return flatNode;
|
||||
}
|
||||
|
||||
/** Whether all the descendants of the node are selected */
|
||||
/** Whether all the descendants of the node are selected. */
|
||||
descendantsAllSelected(node: TodoItemFlatNode): boolean {
|
||||
const descendants = this.treeControl.getDescendants(node);
|
||||
return descendants.every(child => this.checklistSelection.isSelected(child));
|
||||
const descAllSelected = descendants.every(child =>
|
||||
this.checklistSelection.isSelected(child)
|
||||
);
|
||||
return descAllSelected;
|
||||
}
|
||||
|
||||
/** Whether part of the descendants are selected */
|
||||
|
@ -188,6 +191,61 @@ export class TreeChecklistExample {
|
|||
this.checklistSelection.isSelected(node)
|
||||
? this.checklistSelection.select(...descendants)
|
||||
: this.checklistSelection.deselect(...descendants);
|
||||
|
||||
// Force update for the parent
|
||||
descendants.every(child =>
|
||||
this.checklistSelection.isSelected(child)
|
||||
);
|
||||
this.checkAllParentsSelection(node);
|
||||
}
|
||||
|
||||
/** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
|
||||
todoLeafItemSelectionToggle(node: TodoItemFlatNode): void {
|
||||
this.checklistSelection.toggle(node);
|
||||
this.checkAllParentsSelection(node);
|
||||
}
|
||||
|
||||
/* Checks all the parents when a leaf node is selected/unselected */
|
||||
checkAllParentsSelection(node: TodoItemFlatNode): void {
|
||||
let parent: TodoItemFlatNode | null = this.getParentNode(node);
|
||||
while (parent) {
|
||||
this.checkRootNodeSelection(parent);
|
||||
parent = this.getParentNode(parent);
|
||||
}
|
||||
}
|
||||
|
||||
/** Check root node checked state and change it accordingly */
|
||||
checkRootNodeSelection(node: TodoItemFlatNode): void {
|
||||
const nodeSelected = this.checklistSelection.isSelected(node);
|
||||
const descendants = this.treeControl.getDescendants(node);
|
||||
const descAllSelected = descendants.every(child =>
|
||||
this.checklistSelection.isSelected(child)
|
||||
);
|
||||
if (nodeSelected && !descAllSelected) {
|
||||
this.checklistSelection.deselect(node);
|
||||
} else if (!nodeSelected && descAllSelected) {
|
||||
this.checklistSelection.select(node);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the parent node of a node */
|
||||
getParentNode(node: TodoItemFlatNode): TodoItemFlatNode | null {
|
||||
const currentLevel = this.getLevel(node);
|
||||
|
||||
if (currentLevel < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;
|
||||
|
||||
for (let i = startIndex; i >= 0; i--) {
|
||||
const currentNode = this.treeControl.dataNodes[i];
|
||||
|
||||
if (this.getLevel(currentNode) < currentLevel) {
|
||||
return currentNode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Select the category so we can insert the new item. */
|
||||
|
|
|
@ -59,7 +59,7 @@ export class DynamicDataSource {
|
|||
private database: DynamicDatabase) {}
|
||||
|
||||
connect(collectionViewer: CollectionViewer): Observable<DynamicFlatNode[]> {
|
||||
this.treeControl.expansionModel.onChange!.subscribe(change => {
|
||||
this.treeControl.expansionModel.onChange.subscribe(change => {
|
||||
if ((change as SelectionChange<DynamicFlatNode>).added ||
|
||||
(change as SelectionChange<DynamicFlatNode>).removed) {
|
||||
this.handleTreeControl(change as SelectionChange<DynamicFlatNode>);
|
||||
|
|
|
@ -91,7 +91,7 @@ export class FileDatabase {
|
|||
* Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
|
||||
* The return value is the list of `FileNode`.
|
||||
*/
|
||||
buildFileTree(obj: object, level: number): FileNode[] {
|
||||
buildFileTree(obj: {[key: string]: any}, level: number): FileNode[] {
|
||||
return Object.keys(obj).reduce<FileNode[]>((accumulator, key) => {
|
||||
const value = obj[key];
|
||||
const node = new FileNode();
|
||||
|
|
|
@ -84,7 +84,7 @@ export class FileDatabase {
|
|||
* Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
|
||||
* The return value is the list of `FileNode`.
|
||||
*/
|
||||
buildFileTree(obj: object, level: number): FileNode[] {
|
||||
buildFileTree(obj: {[key: string]: any}, level: number): FileNode[] {
|
||||
return Object.keys(obj).reduce<FileNode[]>((accumulator, key) => {
|
||||
const value = obj[key];
|
||||
const node = new FileNode();
|
||||
|
|
Loading…
Reference in New Issue
Block a user