From cb63d4f5d374a38a6de5373dba7745c1d9038ae6 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Mon, 24 Jun 2019 21:52:34 +0200 Subject: [PATCH 1/6] build: make a11y-demo compatible with ivy template type checking --- src/a11y-demo/checkbox/checkbox-a11y.html | 4 ++-- src/a11y-demo/chips/chips-a11y.ts | 3 ++- src/a11y-demo/grid-list/grid-list-a11y.ts | 2 +- src/a11y-demo/input/input-a11y.ts | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/a11y-demo/checkbox/checkbox-a11y.html b/src/a11y-demo/checkbox/checkbox-a11y.html index 5cc86440d2b6..ace111011cf8 100644 --- a/src/a11y-demo/checkbox/checkbox-a11y.html +++ b/src/a11y-demo/checkbox/checkbox-a11y.html @@ -20,12 +20,12 @@

Nested checklist

{{task.name}}
-
+
{{subtask.name}} diff --git a/src/a11y-demo/chips/chips-a11y.ts b/src/a11y-demo/chips/chips-a11y.ts index 15ca727fe122..72d2fc003f8d 100644 --- a/src/a11y-demo/chips/chips-a11y.ts +++ b/src/a11y-demo/chips/chips-a11y.ts @@ -8,6 +8,7 @@ import {Component} from '@angular/core'; import {MatChipInputEvent, MatSnackBar} from '@angular/material'; +import {ThemePalette} from '@angular/material/core'; export interface Person { @@ -22,7 +23,7 @@ export interface Person { }) export class ChipsAccessibilityDemo { visible: boolean = true; - color: string = ''; + color: ThemePalette = undefined; selectable: boolean = true; removable: boolean = true; addOnBlur: boolean = true; diff --git a/src/a11y-demo/grid-list/grid-list-a11y.ts b/src/a11y-demo/grid-list/grid-list-a11y.ts index 7eab81f67ae1..7a80cbd5cadc 100644 --- a/src/a11y-demo/grid-list/grid-list-a11y.ts +++ b/src/a11y-demo/grid-list/grid-list-a11y.ts @@ -39,7 +39,7 @@ export class GridListAccessibilityDemo { fixedCols = 4; fixedRowHeight = 100; - ratioGutter = 1; + ratioGutter = '1px'; fitListHeight = '400px'; ratio = '4:1'; } diff --git a/src/a11y-demo/input/input-a11y.ts b/src/a11y-demo/input/input-a11y.ts index 249f5a85dde9..49a003b1e99d 100644 --- a/src/a11y-demo/input/input-a11y.ts +++ b/src/a11y-demo/input/input-a11y.ts @@ -24,7 +24,7 @@ export class InputAccessibilityDemo { email: string; usd: number; comment: string; - commentMax = 200; + commentMax = '200'; get passwordType() { return this.showPassword ? 'text' : 'password'; } From 9b25d9c2f152a99ca3de15a931a660bccde2e11a Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Mon, 24 Jun 2019 21:54:29 +0200 Subject: [PATCH 2/6] build: make dev-app compatible with ivy template type checking --- src/dev-app/BUILD.bazel | 3 ++ src/dev-app/badge/badge-demo.html | 2 +- src/dev-app/checkbox/checkbox-demo.ts | 15 +++++----- src/dev-app/checkbox/nested-checklist.html | 6 ++-- src/dev-app/chips/chips-demo.ts | 2 +- .../connected-overlay-demo.html | 2 +- src/dev-app/datepicker/datepicker-demo.html | 20 ++++++++----- src/dev-app/datepicker/datepicker-demo.ts | 7 +++-- src/dev-app/expansion/expansion-demo.ts | 10 +++++-- src/dev-app/grid-list/grid-list-demo.ts | 2 +- src/dev-app/input/input-demo.html | 8 ++--- src/dev-app/input/input-demo.ts | 8 +++-- src/dev-app/mdc-checkbox/mdc-checkbox-demo.ts | 15 +++++----- .../mdc-checkbox/nested-checklist.html | 6 ++-- src/dev-app/progress-bar/progress-bar-demo.ts | 3 +- .../progress-spinner/progress-spinner-demo.ts | 3 +- src/dev-app/radio/radio-demo.html | 2 +- src/dev-app/select/select-demo.ts | 30 +++++++++++-------- src/dev-app/sidenav/sidenav-demo.ts | 5 +++- src/dev-app/stepper/stepper-demo.html | 4 +-- .../dynamic-tree-demo/dynamic-database.ts | 6 ++-- .../virtual-scroll/virtual-scroll-demo.html | 16 +++++----- 22 files changed, 103 insertions(+), 72 deletions(-) diff --git a/src/dev-app/BUILD.bazel b/src/dev-app/BUILD.bazel index 6e10a221a7be..3a4facb0a878 100644 --- a/src/dev-app/BUILD.bazel +++ b/src/dev-app/BUILD.bazel @@ -31,6 +31,9 @@ ng_module( ":dev_app_scss", ":theme", ], + # TODO(devversion): Temporarily disabled due to an Ivy template type checking bug + # that is surfaced in the "MdcMenu" demo. The issue is tracked with: COMP-173 + type_check = False, deps = [ "@npm//@angular/animations", "@npm//@angular/common", diff --git a/src/dev-app/badge/badge-demo.html b/src/dev-app/badge/badge-demo.html index 029c183d6bdd..c07828170996 100644 --- a/src/dev-app/badge/badge-demo.html +++ b/src/dev-app/badge/badge-demo.html @@ -6,7 +6,7 @@

Text

Hello - + Hello diff --git a/src/dev-app/checkbox/checkbox-demo.ts b/src/dev-app/checkbox/checkbox-demo.ts index a56c4d3afa27..580c4192aacc 100644 --- a/src/dev-app/checkbox/checkbox-demo.ts +++ b/src/dev-app/checkbox/checkbox-demo.ts @@ -8,6 +8,7 @@ import {Component, Directive} from '@angular/core'; import {MAT_CHECKBOX_CLICK_ACTION} from '@angular/material/checkbox'; +import {ThemePalette} from '@angular/material/core'; import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations'; @@ -96,7 +97,7 @@ export class CheckboxDemo { isIndeterminate: boolean = false; isChecked: boolean = false; isDisabled: boolean = false; - labelPosition: string = 'after'; + labelPosition: 'before' | 'after' = 'after'; useAlternativeColor: boolean = false; demoRequired = false; @@ -104,12 +105,12 @@ export class CheckboxDemo { demoChecked = false; demoDisabled = false; demoIndeterminate = false; - demoLabel = null; - demoLabelledBy = null; - demoId = null; - demoName = null; - demoValue = null; - demoColor = 'primary'; + demoLabel: string; + demoLabelledBy: string; + demoId: string; + demoName: string; + demoValue: string; + demoColor: ThemePalette = 'primary'; demoDisableRipple = false; demoHideLabel = false; diff --git a/src/dev-app/checkbox/nested-checklist.html b/src/dev-app/checkbox/nested-checklist.html index 6a4ab3e617ab..8279e2a5d2f6 100644 --- a/src/dev-app/checkbox/nested-checklist.html +++ b/src/dev-app/checkbox/nested-checklist.html @@ -3,12 +3,12 @@

Tasks

  • + [indeterminate]="someComplete(task.subtasks!)" + (change)="setAllCompleted(task.subtasks!, $event.checked)">

    {{task.name}}

      -
    • +
    • {{subtask.name}} diff --git a/src/dev-app/chips/chips-demo.ts b/src/dev-app/chips/chips-demo.ts index 8a5c79572367..fbf3e2b7813c 100644 --- a/src/dev-app/chips/chips-demo.ts +++ b/src/dev-app/chips/chips-demo.ts @@ -30,7 +30,7 @@ export interface DemoColor { export class ChipsDemo { tabIndex = 0; visible = true; - color = ''; + color: ThemePalette = undefined; selectable = true; removable = true; addOnBlur = true; diff --git a/src/dev-app/connected-overlay/connected-overlay-demo.html b/src/dev-app/connected-overlay/connected-overlay-demo.html index 77dd7445d092..9ab9d62c941f 100644 --- a/src/dev-app/connected-overlay/connected-overlay-demo.html +++ b/src/dev-app/connected-overlay/connected-overlay-demo.html @@ -97,7 +97,7 @@

      Options

  • diff --git a/src/dev-app/datepicker/datepicker-demo.html b/src/dev-app/datepicker/datepicker-demo.html index 3abeedf1d183..891e4eaac59e 100644 --- a/src/dev-app/datepicker/datepicker-demo.html +++ b/src/dev-app/datepicker/datepicker-demo.html @@ -51,7 +51,7 @@

    Result

    [(ngModel)]="date" [min]="minDate" [max]="maxDate" - [matDatepickerFilter]="filterOdd ? dateFilter : null" + [matDatepickerFilter]="filterOdd ? dateFilter : undefined" [disabled]="inputDisabled" (dateInput)="onDateInput($event)" (dateChange)="onDateChange($event)"> @@ -81,7 +81,7 @@

    Result

    [min]="minDate" [max]="maxDate" [disabled]="inputDisabled" - [matDatepickerFilter]="filterOdd ? dateFilter : null" + [matDatepickerFilter]="filterOdd ? dateFilter : undefined" placeholder="Pick a date"> Input disabled datepicker Input disabled + [matDatepickerFilter]="filterOdd ? dateFilter : undefined" disabled> @@ -111,7 +111,7 @@

    Input disabled via FormControl

    FormControl disabled + [max]="maxDate" [matDatepickerFilter]="filterOdd ? dateFilter : undefined"> @@ -127,7 +127,7 @@

    Input disabled, datepicker popup enabled

    Input disabled, datepicker enabled + [max]="maxDate" [matDatepickerFilter]="filterOdd ? dateFilter : undefined"> @@ -138,8 +138,14 @@

    Datepicker with value property binding

    Value binding - + + diff --git a/src/dev-app/datepicker/datepicker-demo.ts b/src/dev-app/datepicker/datepicker-demo.ts index d30a8c19ab87..897ec912a916 100644 --- a/src/dev-app/datepicker/datepicker-demo.ts +++ b/src/dev-app/datepicker/datepicker-demo.ts @@ -49,15 +49,16 @@ export class DatepickerDemo { dateCtrl = new FormControl(); - dateFilter = - (date: Date) => !(date.getFullYear() % 2) && (date.getMonth() % 2) && !(date.getDate() % 2) - onDateInput = (e: MatDatepickerInputEvent) => this.lastDateInput = e.value; onDateChange = (e: MatDatepickerInputEvent) => this.lastDateChange = e.value; // pass custom header component type as input customHeader = CustomHeader; customHeaderNgContent = CustomHeaderNgContent; + + dateFilter(date: Date|null) { + return !!(date && !(date.getFullYear() % 2) && date.getMonth() % 2 && !(date.getDate() % 2)); + } } // Custom header component for datepicker diff --git a/src/dev-app/expansion/expansion-demo.ts b/src/dev-app/expansion/expansion-demo.ts index 42d289c30e2b..dd4753b68c9d 100644 --- a/src/dev-app/expansion/expansion-demo.ts +++ b/src/dev-app/expansion/expansion-demo.ts @@ -7,7 +7,11 @@ */ import {Component, ViewChild} from '@angular/core'; -import {MatAccordion} from '@angular/material/expansion'; +import { + MatAccordion, + MatAccordionDisplayMode, + MatAccordionTogglePosition +} from '@angular/material/expansion'; @Component({ @@ -19,12 +23,12 @@ import {MatAccordion} from '@angular/material/expansion'; export class ExpansionDemo { @ViewChild(MatAccordion, {static: false}) accordion: MatAccordion; - displayMode = 'default'; + displayMode: MatAccordionDisplayMode = 'default'; multi = false; hideToggle = false; disabled = false; showPanel3 = true; - togglePosition = 'after'; + togglePosition: MatAccordionTogglePosition = 'after'; expandedHeight: string; collapsedHeight: string; events: string[] = []; diff --git a/src/dev-app/grid-list/grid-list-demo.ts b/src/dev-app/grid-list/grid-list-demo.ts index be82d7b85196..4039530112ad 100644 --- a/src/dev-app/grid-list/grid-list-demo.ts +++ b/src/dev-app/grid-list/grid-list-demo.ts @@ -35,7 +35,7 @@ export class GridListDemo { basicRowHeight = 80; fixedCols = 4; fixedRowHeight = 100; - ratioGutter = 1; + ratioGutter = '1px'; fitListHeight = '400px'; ratio = '4:1'; diff --git a/src/dev-app/input/input-demo.html b/src/dev-app/input/input-demo.html index 5defa027774d..90cbe268c5d6 100644 --- a/src/dev-app/input/input-demo.html +++ b/src/dev-app/input/input-demo.html @@ -362,7 +362,7 @@

    Textarea

    Both: Email address - + email   @gmail.com @@ -550,9 +550,9 @@

    Regular <textarea> with maxRows and minRows

    - + [cdkAutosizeMinRows]="parseNumber(minRows.value)" + [cdkAutosizeMaxRows]="parseNumber(maxRows.value)"> +

    <textarea> with mat-form-field

    diff --git a/src/dev-app/input/input-demo.ts b/src/dev-app/input/input-demo.ts index b8708115820f..6e5ab3d76fb0 100644 --- a/src/dev-app/input/input-demo.ts +++ b/src/dev-app/input/input-demo.ts @@ -8,7 +8,7 @@ import {ChangeDetectionStrategy, Component} from '@angular/core'; import {FormControl, Validators} from '@angular/forms'; -import {ErrorStateMatcher} from '@angular/material/core'; +import {ErrorStateMatcher, FloatLabelType} from '@angular/material/core'; let max = 5; @@ -23,7 +23,7 @@ const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA styleUrls: ['input-demo.css'], }) export class InputDemo { - floatingLabel = 'auto'; + floatingLabel: FloatLabelType = 'auto'; color: boolean; requiredField: boolean; hideRequiredMarker: boolean; @@ -92,4 +92,8 @@ export class InputDemo { this.placeholderTestControl.markAsUntouched() : this.placeholderTestControl.markAsTouched(); } + + parseNumber(value: string): number { + return Number(value); + } } diff --git a/src/dev-app/mdc-checkbox/mdc-checkbox-demo.ts b/src/dev-app/mdc-checkbox/mdc-checkbox-demo.ts index 1329135bb3a6..83e3e40389ac 100644 --- a/src/dev-app/mdc-checkbox/mdc-checkbox-demo.ts +++ b/src/dev-app/mdc-checkbox/mdc-checkbox-demo.ts @@ -8,6 +8,7 @@ import {Component, Directive} from '@angular/core'; import {MAT_CHECKBOX_CLICK_ACTION} from '@angular/material/checkbox'; +import {ThemePalette} from '@angular/material/core'; import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations'; @@ -97,7 +98,7 @@ export class MdcCheckboxDemo { isIndeterminate: boolean = false; isChecked: boolean = false; isDisabled: boolean = false; - labelPosition: string = 'after'; + labelPosition: 'before'|'after' = 'after'; useAlternativeColor: boolean = false; demoRequired = false; @@ -105,12 +106,12 @@ export class MdcCheckboxDemo { demoChecked = false; demoDisabled = false; demoIndeterminate = false; - demoLabel = null; - demoLabelledBy = null; - demoId = null; - demoName = null; - demoValue = null; - demoColor = 'primary'; + demoLabel: string; + demoLabelledBy: string; + demoId: string; + demoName: string; + demoValue: string; + demoColor: ThemePalette = 'primary'; demoDisableRipple = false; demoHideLabel = false; diff --git a/src/dev-app/mdc-checkbox/nested-checklist.html b/src/dev-app/mdc-checkbox/nested-checklist.html index 6a4ab3e617ab..8279e2a5d2f6 100644 --- a/src/dev-app/mdc-checkbox/nested-checklist.html +++ b/src/dev-app/mdc-checkbox/nested-checklist.html @@ -3,12 +3,12 @@

    Tasks

  • + [indeterminate]="someComplete(task.subtasks!)" + (change)="setAllCompleted(task.subtasks!, $event.checked)">

    {{task.name}}

      -
    • +
    • {{subtask.name}} diff --git a/src/dev-app/progress-bar/progress-bar-demo.ts b/src/dev-app/progress-bar/progress-bar-demo.ts index 20038ee88934..b17f2a218ec0 100644 --- a/src/dev-app/progress-bar/progress-bar-demo.ts +++ b/src/dev-app/progress-bar/progress-bar-demo.ts @@ -7,6 +7,7 @@ */ import {Component} from '@angular/core'; +import {ThemePalette} from '@angular/material/core'; // TODO(josephperrott): Add an automatically filling example progress bar. @@ -18,7 +19,7 @@ import {Component} from '@angular/core'; styleUrls: ['progress-bar-demo.css'], }) export class ProgressBarDemo { - color: string = 'primary'; + color: ThemePalette = 'primary'; determinateProgressValue: number = 30; determinateAnimationEndValue: number; bufferAnimationEndValue: number; diff --git a/src/dev-app/progress-spinner/progress-spinner-demo.ts b/src/dev-app/progress-spinner/progress-spinner-demo.ts index 8ed811215bc5..9f0281eb1baa 100644 --- a/src/dev-app/progress-spinner/progress-spinner-demo.ts +++ b/src/dev-app/progress-spinner/progress-spinner-demo.ts @@ -7,6 +7,7 @@ */ import {Component} from '@angular/core'; +import {ThemePalette} from '@angular/material/core'; @Component({ @@ -17,7 +18,7 @@ import {Component} from '@angular/core'; }) export class ProgressSpinnerDemo { progressValue = 60; - color = 'primary'; + color: ThemePalette = 'primary'; isDeterminate = true; step(val: number) { diff --git a/src/dev-app/radio/radio-demo.html b/src/dev-app/radio/radio-demo.html index 2a8c2ac757d0..55625724d9fd 100644 --- a/src/dev-app/radio/radio-demo.html +++ b/src/dev-app/radio/radio-demo.html @@ -44,7 +44,7 @@

      Dynamic Example

      name="my_options" [disabled]="isDisabled" [required]="isRequired" - [labelPosition]="isAlignEnd ? 'end' : 'start'"> + [labelPosition]="isAlignEnd ? 'before' : 'after'"> Option 1 Option 2 Option 3 diff --git a/src/dev-app/select/select-demo.ts b/src/dev-app/select/select-demo.ts index 21469fbc7bd4..9a98b2013c16 100644 --- a/src/dev-app/select/select-demo.ts +++ b/src/dev-app/select/select-demo.ts @@ -8,7 +8,7 @@ import {Component} from '@angular/core'; import {FormControl, Validators} from '@angular/forms'; -import {ErrorStateMatcher} from '@angular/material/core'; +import {ErrorStateMatcher, FloatLabelType, ThemePalette} from '@angular/material/core'; import {MatSelectChange} from '@angular/material/select'; /** Error any time control is invalid */ @@ -41,12 +41,12 @@ export class SelectDemo { currentDigimon: string; currentAppearanceValue: string | null; latestChangeEvent: MatSelectChange; - floatLabel = 'auto'; + floatLabel: FloatLabelType = 'auto'; drinksWidth = 'default'; foodControl = new FormControl('pizza-1'); topHeightCtrl = new FormControl(0); - drinksTheme = 'primary'; - pokemonTheme = 'primary'; + drinksTheme: ThemePalette = 'primary'; + pokemonTheme: ThemePalette = 'primary'; compareByValue = true; selectFormControl = new FormControl('', Validators.required); @@ -58,15 +58,19 @@ export class SelectDemo { ]; drinks = [ - {value: 'coke-0', viewValue: 'Coke'}, - {value: 'long-name-1', viewValue: 'Decaf Chocolate Brownie Vanilla Gingerbread Frappuccino'}, - {value: 'water-2', viewValue: 'Water'}, - {value: 'pepper-3', viewValue: 'Dr. Pepper'}, - {value: 'coffee-4', viewValue: 'Coffee'}, - {value: 'tea-5', viewValue: 'Tea'}, - {value: 'juice-6', viewValue: 'Orange juice'}, - {value: 'wine-7', viewValue: 'Wine'}, - {value: 'milk-8', viewValue: 'Milk'}, + {value: 'coke-0', viewValue: 'Coke', disabled: false}, + { + value: 'long-name-1', + viewValue: 'Decaf Chocolate Brownie Vanilla Gingerbread Frappuccino', + disabled: false + }, + {value: 'water-2', viewValue: 'Water', disabled: false}, + {value: 'pepper-3', viewValue: 'Dr. Pepper', disabled: false}, + {value: 'coffee-4', viewValue: 'Coffee', disabled: false}, + {value: 'tea-5', viewValue: 'Tea', disabled: false}, + {value: 'juice-6', viewValue: 'Orange juice', disabled: false}, + {value: 'wine-7', viewValue: 'Wine', disabled: false}, + {value: 'milk-8', viewValue: 'Milk', disabled: true}, ]; pokemon = [ diff --git a/src/dev-app/sidenav/sidenav-demo.ts b/src/dev-app/sidenav/sidenav-demo.ts index 950ace5e8134..071cb0434ea5 100644 --- a/src/dev-app/sidenav/sidenav-demo.ts +++ b/src/dev-app/sidenav/sidenav-demo.ts @@ -8,6 +8,7 @@ import {Component} from '@angular/core'; +type SidenavModeType = 'over' | 'push' | 'side'; @Component({ moduleId: module.id, @@ -25,7 +26,9 @@ export class SidenavDemo { showFooter = false; modeIndex = 0; hasBackdrop: boolean; - get mode() { return ['side', 'over', 'push'][this.modeIndex]; } + get mode(): SidenavModeType { + return (['side', 'over', 'push'] as SidenavModeType[])[this.modeIndex]; + } get fixedTop() { return this.fixed && this.showHeader && !this.coverHeader ? 64 : 0; } get fixedBottom() { return this.fixed && this.showFooter && !this.coverHeader ? 64 : 0; } } diff --git a/src/dev-app/stepper/stepper-demo.html b/src/dev-app/stepper/stepper-demo.html index d932ec3c1be6..a36b65a37d19 100644 --- a/src/dev-app/stepper/stepper-demo.html +++ b/src/dev-app/stepper/stepper-demo.html @@ -5,7 +5,7 @@

      Linear Vertical Stepper Demo using a single form

      - + Fill out your name First name @@ -23,7 +23,7 @@

      Linear Vertical Stepper Demo using a single form

  • - +
    Fill out your email address
    diff --git a/src/dev-app/tree/dynamic-tree-demo/dynamic-database.ts b/src/dev-app/tree/dynamic-tree-demo/dynamic-database.ts index c51d609e4243..7bfd90ae030d 100644 --- a/src/dev-app/tree/dynamic-tree-demo/dynamic-database.ts +++ b/src/dev-app/tree/dynamic-tree-demo/dynamic-database.ts @@ -7,7 +7,7 @@ */ import {Injectable} from '@angular/core'; import {FlatTreeControl} from '@angular/cdk/tree'; -import {CollectionViewer, SelectionChange} from '@angular/cdk/collections'; +import {CollectionViewer, DataSource, SelectionChange} from '@angular/cdk/collections'; import {BehaviorSubject, merge, Observable} from 'rxjs'; import {map} from 'rxjs/operators'; @@ -54,7 +54,7 @@ export class DynamicDatabase { * the output is a list of `FileNode`-s with a nested structure. */ @Injectable() -export class DynamicDataSource { +export class DynamicDataSource implements DataSource { dataChange: BehaviorSubject = new BehaviorSubject([]); @@ -77,6 +77,8 @@ export class DynamicDataSource { return merge(collectionViewer.viewChange, this.dataChange).pipe(map(() => this.data)); } + disconnect(): void {} + /** Handle expand/collapse behaviors */ handleTreeControl(change: SelectionChange) { if (change.added) { diff --git a/src/dev-app/virtual-scroll/virtual-scroll-demo.html b/src/dev-app/virtual-scroll/virtual-scroll-demo.html index 40792b7aab14..b6ce2228804d 100644 --- a/src/dev-app/virtual-scroll/virtual-scroll-demo.html +++ b/src/dev-app/virtual-scroll/virtual-scroll-demo.html @@ -87,7 +87,7 @@

    Observable data

    -
    Item #{{i}} - ({{size}}px)
    @@ -98,7 +98,7 @@

    No trackBy

    -
    {{state.name}}
    {{state.capital}}
    @@ -110,7 +110,7 @@

    trackBy index

    -
    {{state.name}}
    {{state.capital}}
    @@ -122,7 +122,7 @@

    trackBy state name

    -
    {{state.name}}
    {{state.capital}}
    @@ -133,7 +133,7 @@

    Use with <ol>

      -
    1. +
    2. {{state.name}} - {{state.capital}}
    @@ -143,7 +143,7 @@

    Use with <ul>

      -
    • +
    • {{state.name}} - {{state.capital}}
    @@ -153,7 +153,7 @@

    Use with <dl>

    - +
    {{state.name}}
    {{state.capital}}
    @@ -164,7 +164,7 @@

    Use with <table>

    - + From e7ca296bc8ada5c80ee1ddf89102df299b93ccdb Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Mon, 24 Jun 2019 21:59:25 +0200 Subject: [PATCH 3/6] fix(stepper): unable to pass FormGroup as step control with strict type checking Before #15134 landed, the stepper accepted an`AbstractControl` from `@angular/forms`. Unfortunately this PR accidentally changed the type for the `stepControl` input from `AbstractControl` to `FormControl`. This means that with strict template type checking, passing a `FormGroup` (like we do in our dev-app various times) causes type check failures. We need to adjust the `stepControl` type to accept an abstract control which is the base of a `FormControl` and `FormmGroup`. --- src/cdk/stepper/stepper.ts | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index 655b7bfd22c5..4edd45b2156d 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -9,7 +9,8 @@ import {FocusableOption, FocusKeyManager} from '@angular/cdk/a11y'; import {Direction, Directionality} from '@angular/cdk/bidi'; import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion'; -import {END, ENTER, HOME, SPACE, hasModifierKey} from '@angular/cdk/keycodes'; +import {END, ENTER, hasModifierKey, HOME, SPACE} from '@angular/cdk/keycodes'; +import {DOCUMENT} from '@angular/common'; import { AfterViewInit, ChangeDetectionStrategy, @@ -18,10 +19,11 @@ import { ContentChild, ContentChildren, Directive, - EventEmitter, ElementRef, + EventEmitter, forwardRef, Inject, + InjectionToken, Input, OnChanges, OnDestroy, @@ -31,13 +33,11 @@ import { TemplateRef, ViewChild, ViewEncapsulation, - InjectionToken, } from '@angular/core'; -import {DOCUMENT} from '@angular/common'; -import {CdkStepLabel} from './step-label'; -import {Observable, Subject, of as obaservableOf} from 'rxjs'; +import {Observable, of as obaservableOf, Subject} from 'rxjs'; import {startWith, takeUntil} from 'rxjs/operators'; import {CdkStepHeader} from './step-header'; +import {CdkStepLabel} from './step-label'; /** Used to generate unique ID for each stepper component. */ let nextId = 0; @@ -124,7 +124,7 @@ export class CdkStep implements OnChanges { @ViewChild(TemplateRef, {static: true}) content: TemplateRef; /** The top level abstract control of the step. */ - @Input() stepControl: FormControlLike; + @Input() stepControl: AbstractControlLike; /** Whether user has seen the expanded step content or not. */ interacted = false; @@ -512,14 +512,13 @@ export class CdkStepper implements AfterViewInit, OnDestroy { } } - /** - * Simplified representation of a FormControl from @angular/forms. + * Simplified representation of an "AbstractControl" from @angular/forms. * Used to avoid having to bring in @angular/forms for a single optional interface. * @docs-private */ -interface FormControlLike { - asyncValidator: () => any | null; +interface AbstractControlLike { + asyncValidator: ((control: any) => any) | null; dirty: boolean; disabled: boolean; enabled: boolean; @@ -528,21 +527,21 @@ interface FormControlLike { parent: any; pending: boolean; pristine: boolean; - root: FormControlLike; + root: AbstractControlLike; status: string; statusChanges: Observable; touched: boolean; untouched: boolean; updateOn: any; valid: boolean; - validator: () => any | null; + validator: ((control: any) => any) | null; value: any; valueChanges: Observable; clearAsyncValidators(): void; clearValidators(): void; disable(opts?: any): void; enable(opts?: any): void; - get(path: (string | number)[] | string): FormControlLike | null; + get(path: (string | number)[] | string): AbstractControlLike | null; getError(errorCode: string, path?: (string | number)[] | string): any; hasError(errorCode: string, path?: (string | number)[] | string): boolean; markAllAsTouched(): void; @@ -553,15 +552,15 @@ interface FormControlLike { markAsUntouched(opts?: any): void; patchValue(value: any, options?: Object): void; reset(value?: any, options?: Object): void; - setAsyncValidators(newValidator: () => any | (() => any)[] | null): void; + setAsyncValidators(newValidator: (control: any) => any | + ((control: any) => any)[] | null): void; setErrors(errors: {[key: string]: any} | null, opts?: any): void; setParent(parent: any): void; - setValidators(newValidator: () => any | (() => any)[] | null): void; + setValidators(newValidator: (control: any) => any | + ((control: any) => any)[] | null): void; setValue(value: any, options?: Object): void; updateValueAndValidity(opts?: any): void; patchValue(value: any, options?: any): void; - registerOnChange(fn: Function): void; - registerOnDisabledChange(fn: (isDisabled: boolean) => void): void; reset(formState?: any, options?: any): void; setValue(value: any, options?: any): void; } From f15eac57e577b195cd42f8a38ada2c747eea1264 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Mon, 24 Jun 2019 22:01:35 +0200 Subject: [PATCH 4/6] build: components should be built with strict type checking All components which are exported should be built with Ivy's strict template type checking. This guarantees maximum safety for template bindings and increases general code health in the components repository. --- src/cdk/stepper/stepper.ts | 10 +++++++--- src/material/button-toggle/button-toggle.html | 2 +- src/material/core/option/option.html | 2 +- src/material/datepicker/calendar-body.ts | 17 ++++++++++++----- src/material/datepicker/year-view.html | 4 ++-- src/material/select/select.ts | 9 +++++++-- src/material/stepper/stepper-horizontal.html | 4 ++-- src/material/stepper/stepper-vertical.html | 2 +- src/material/tabs/tab-body.ts | 8 ++++---- src/material/tabs/tab-group.html | 16 ++++++++-------- tools/public_api_guard/cdk/stepper.d.ts | 2 +- tools/public_api_guard/material/datepicker.d.ts | 14 +++++--------- tools/public_api_guard/material/select.d.ts | 7 +------ tools/public_api_guard/material/tabs.d.ts | 2 +- 14 files changed, 53 insertions(+), 46 deletions(-) diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index 4edd45b2156d..57d521ac25aa 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -34,7 +34,7 @@ import { ViewChild, ViewEncapsulation, } from '@angular/core'; -import {Observable, of as obaservableOf, Subject} from 'rxjs'; +import {Observable, of as observableOf, Subject} from 'rxjs'; import {startWith, takeUntil} from 'rxjs/operators'; import {CdkStepHeader} from './step-header'; import {CdkStepLabel} from './step-label'; @@ -254,7 +254,11 @@ export class CdkStepper implements AfterViewInit, OnDestroy { @ContentChildren(CdkStep) _steps: QueryList; /** The list of step components that the stepper is holding. */ - get steps(): QueryList { + get steps(): QueryList { + // Note that the query list cannot be used in the template as iterable + // because it breaks Ivy's strict template type checking. Therefore the + // template currently uses "steps.toArray()". Read more about this: + // https://github.com/angular/angular/issues/29842 return this._steps; } @@ -331,7 +335,7 @@ export class CdkStepper implements AfterViewInit, OnDestroy { .withWrap() .withVerticalOrientation(this._orientation === 'vertical'); - (this._dir ? this._dir.change as Observable : obaservableOf()) + (this._dir ? this._dir.change as Observable : observableOf()) .pipe(startWith(this._layoutDirection()), takeUntil(this._destroyed)) .subscribe(direction => this._keyManager.withHorizontalOrientation(direction)); diff --git a/src/material/button-toggle/button-toggle.html b/src/material/button-toggle/button-toggle.html index 400550c5bbdc..1a5025796c3b 100644 --- a/src/material/button-toggle/button-toggle.html +++ b/src/material/button-toggle/button-toggle.html @@ -3,7 +3,7 @@ [id]="buttonId" [attr.tabindex]="disabled ? -1 : tabIndex" [attr.aria-pressed]="checked" - [disabled]="disabled || null" + [disabled]="disabled" [attr.name]="name || null" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledby" diff --git a/src/material/core/option/option.html b/src/material/core/option/option.html index c6316b889438..75d6d352c9b2 100644 --- a/src/material/core/option/option.html +++ b/src/material/core/option/option.html @@ -1,5 +1,5 @@ + [state]="selected ? 'checked' : 'unchecked'" [disabled]="disabled"> diff --git a/src/material/datepicker/calendar-body.ts b/src/material/datepicker/calendar-body.ts index 1112ccfddcef..3ff0616a5f60 100644 --- a/src/material/datepicker/calendar-body.ts +++ b/src/material/datepicker/calendar-body.ts @@ -23,7 +23,8 @@ import {take} from 'rxjs/operators'; /** * Extra CSS classes that can be associated with a calendar cell. */ -export type MatCalendarCellCssClasses = string | string[] | Set | {[key: string]: any}; +export type MatCalendarCellCssClasses = string | string[] | Set | {[key: string]: any} + | undefined; /** * An internal class that represents the data corresponding to a single calendar cell. @@ -63,11 +64,17 @@ export class MatCalendarBody implements OnChanges { /** The cells to display in the table. */ @Input() rows: MatCalendarCell[][]; - /** The value in the table that corresponds to today. */ - @Input() todayValue: number; + /** + * The value in the table that corresponds to today. Can be set to null if no + * cell in the table corresponds to today. + */ + @Input() todayValue: number|null; - /** The value in the table that is currently selected. */ - @Input() selectedValue: number; + /** + * The value in the table that is currently selected. Null if no cell in the + * table is selected. + */ + @Input() selectedValue: number|null; /** The minimum number of free cells needed to fit the label in the first row. */ @Input() labelMinRequiredCells: number; diff --git a/src/material/datepicker/year-view.html b/src/material/datepicker/year-view.html index 290557e88f2d..d9a9ac74a313 100644 --- a/src/material/datepicker/year-view.html +++ b/src/material/datepicker/year-view.html @@ -5,8 +5,8 @@ - +
    -
    +
    0)) { + if ((dir == 'ltr' && origin <= 0) || (dir == 'rtl' && origin > 0)) { return 'left-origin-center'; } diff --git a/src/material/tabs/tab-group.html b/src/material/tabs/tab-group.html index 2654b7809d0b..1eceb1009c2f 100644 --- a/src/material/tabs/tab-group.html +++ b/src/material/tabs/tab-group.html @@ -1,10 +1,10 @@ + [selectedIndex]="selectedIndex || 0" + [disableRipple]="disableRipple" + (indexFocused)="_focusChanged($event)" + (selectFocusedIndex)="selectedIndex = $event">
    {{state.name}} {{state.capital}}