Updated Angular Material elements

Updated the changelog
This commit is contained in:
sercan 2018-10-19 00:31:01 +03:00
parent 6fadc29e4c
commit 60ab983730
77 changed files with 1012 additions and 709 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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>

View File

@ -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'
}
]
},

View File

@ -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'],
})

View File

@ -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>

View File

@ -0,0 +1 @@
/** No CSS for this example */

View File

@ -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>

View File

@ -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 {}

View File

@ -1,4 +1,4 @@
.button-row button,
.button-row a {
.example-button-row button,
.example-button-row a {
margin-right: 8px;
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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() {}
}

View File

@ -1,7 +0,0 @@
table {
width: 100%;
}
th {
text-align: left;
}

View File

@ -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>

View File

@ -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() {}
}

View File

@ -1,4 +0,0 @@
.example-tree-node {
display: flex;
align-items: center;
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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 {

View File

@ -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 */

View File

@ -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')">

View File

@ -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 {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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">&ndash;</span>
<input class="example-tel-input-element" formControlName="exchange" size="3">
<span class="example-tel-input-spacer">&ndash;</span>
<input class="example-tel-input-element" formControlName="subscriber" size="4">
</div>

View File

@ -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 */

View File

@ -1,7 +1,5 @@
<div [formGroup]="parts">
<input class="area" formControlName="area" size="3">
<span>&ndash;</span>
<input class="exchange" formControlName="exchange" size="3">
<span>&ndash;</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>

View File

@ -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 {}

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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();
}

View File

@ -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>

View File

@ -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'}
];
}

View File

@ -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>

View File

@ -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!'},

View File

@ -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>

View File

@ -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>

View File

@ -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);
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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>

View File

@ -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]
});
}
}

View File

@ -0,0 +1 @@
/** No CSS for this example */

View File

@ -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>

View File

@ -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]
});
}
}

View File

@ -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>

View File

@ -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]
});
}
}

View File

@ -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']
})

View File

@ -0,0 +1,3 @@
.mat-tab-group {
margin-bottom: 48px;
}

View File

@ -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>

View File

@ -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 {}

View File

@ -0,0 +1,3 @@
table {
width: 100%;
}

View File

@ -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>

View File

@ -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];
}
}

View File

@ -0,0 +1,3 @@
table {
width: 100%;
}

View File

@ -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>

View 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));
}
}

View 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>

View File

@ -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);
}
}

View File

@ -1,6 +1,5 @@
.example-button {
display: block;
width: 48px;
margin: 80px auto 400px;
}

View File

@ -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>

View File

@ -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. */

View File

@ -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>);

View File

@ -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();

View File

@ -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();