+
\ No newline at end of file
From ead7deba8e170f399909ccd3eb3e84815572cd0b Mon Sep 17 00:00:00 2001
From: mmalerba
Date: Tue, 17 Jul 2018 08:09:09 -0700
Subject: [PATCH 002/189] virtual-scroll: Avoid using bypassSecurityTrustStyle
which is banned in google3 (#12181)
---
.../scrolling/virtual-scroll-viewport.html | 3 +-
.../scrolling/virtual-scroll-viewport.spec.ts | 12 --------
.../scrolling/virtual-scroll-viewport.ts | 29 ++++++++++---------
3 files changed, 16 insertions(+), 28 deletions(-)
diff --git a/src/cdk-experimental/scrolling/virtual-scroll-viewport.html b/src/cdk-experimental/scrolling/virtual-scroll-viewport.html
index 5fc18943645a..e545f0ff4dd7 100644
--- a/src/cdk-experimental/scrolling/virtual-scroll-viewport.html
+++ b/src/cdk-experimental/scrolling/virtual-scroll-viewport.html
@@ -2,8 +2,7 @@
Wrap the rendered content in an element that will be used to offset it based on the scroll
position.
-->
-
+
+
{{_control.placeholder}}
@@ -46,7 +46,7 @@
-
+
` to specify the label and the `placeholder` attribute to specify the
* placeholder.
- * @deletion-target 8.0.0
+ * @breaking-change 8.0.0
*/
@Directive({
selector: 'mat-placeholder'
diff --git a/src/lib/input/autosize.ts b/src/lib/input/autosize.ts
index 3ee75b91a082..3cbe5d7f04b8 100644
--- a/src/lib/input/autosize.ts
+++ b/src/lib/input/autosize.ts
@@ -13,7 +13,7 @@ import {Directive, Input} from '@angular/core';
/**
* Directive to automatically resize a textarea to fit its content.
* @deprecated Use `cdkTextareaAutosize` from `@angular/cdk/text-field` instead.
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
@Directive({
selector: 'textarea[mat-autosize], textarea[matTextareaAutosize]',
diff --git a/src/lib/input/input.ts b/src/lib/input/input.ts
index cd9603ca2f57..f55cd48687a0 100644
--- a/src/lib/input/input.ts
+++ b/src/lib/input/input.ts
@@ -62,7 +62,7 @@ export const _MatInputMixinBase = mixinErrorState(MatInputBase);
exportAs: 'matInput',
host: {
/**
- * @deletion-target 7.0.0 remove .mat-form-field-autofill-control in favor of AutofillMonitor.
+ * @breaking-change 7.0.0 remove .mat-form-field-autofill-control in favor of AutofillMonitor.
*/
'class': 'mat-input-element mat-form-field-autofill-control',
'[class.mat-input-server]': '_isServer',
diff --git a/src/lib/list/list.ts b/src/lib/list/list.ts
index 744ed61063df..55011dea74a6 100644
--- a/src/lib/list/list.ts
+++ b/src/lib/list/list.ts
@@ -96,7 +96,7 @@ export class MatListSubheaderCssMatStyler {}
exportAs: 'matListItem',
host: {
'class': 'mat-list-item',
- // @deletion-target 7.0.0 Remove `mat-list-item-avatar` in favor of `mat-list-item-with-avatar`.
+ // @breaking-change 7.0.0 Remove `mat-list-item-avatar` in favor of `mat-list-item-with-avatar`.
'[class.mat-list-item-avatar]': '_avatar || _icon',
'[class.mat-list-item-with-avatar]': '_avatar || _icon',
'(focus)': '_handleFocus()',
diff --git a/src/lib/menu/menu-animations.ts b/src/lib/menu/menu-animations.ts
index 76705e2f3ce2..7ba329b26750 100644
--- a/src/lib/menu/menu-animations.ts
+++ b/src/lib/menu/menu-animations.ts
@@ -73,12 +73,12 @@ export const matMenuAnimations: {
/**
* @deprecated
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
export const fadeInItems = matMenuAnimations.fadeInItems;
/**
* @deprecated
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
export const transformMenu = matMenuAnimations.transformMenu;
diff --git a/src/lib/menu/menu-directive.ts b/src/lib/menu/menu-directive.ts
index b9363dfa3d27..e9687b2f7e86 100644
--- a/src/lib/menu/menu-directive.ts
+++ b/src/lib/menu/menu-directive.ts
@@ -162,7 +162,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnI
/**
* List of the items inside of a menu.
* @deprecated
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
@ContentChildren(MatMenuItem) items: QueryList;
@@ -211,7 +211,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnI
* menu template that displays in the overlay container. Otherwise, it's difficult
* to style the containing menu from outside the component.
* @deprecated Use `panelClass` instead.
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
@Input()
get classList(): string { return this.panelClass; }
@@ -224,7 +224,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnI
/**
* Event emitted when the menu is closed.
* @deprecated Switch to `closed` instead
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
@Output() close = this.closed;
@@ -371,13 +371,13 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnI
/** Starts the enter animation. */
_startAnimation() {
- // @deletion-target 7.0.0 Combine with _resetAnimation.
+ // @breaking-change 7.0.0 Combine with _resetAnimation.
this._panelAnimationState = 'enter';
}
/** Resets the panel animation to its initial state. */
_resetAnimation() {
- // @deletion-target 7.0.0 Combine with _startAnimation.
+ // @breaking-change 7.0.0 Combine with _startAnimation.
this._panelAnimationState = 'void';
}
diff --git a/src/lib/menu/menu-item.ts b/src/lib/menu/menu-item.ts
index 54ed0baff60b..4a721fc1153a 100644
--- a/src/lib/menu/menu-item.ts
+++ b/src/lib/menu/menu-item.ts
@@ -75,7 +75,7 @@ export class MatMenuItem extends _MatMenuItemMixinBase
private _focusMonitor?: FocusMonitor,
@Inject(MAT_MENU_PANEL) @Optional() private _parentMenu?: MatMenuPanel) {
- // @deletion-target 7.0.0 make `_focusMonitor` and `document` required params.
+ // @breaking-change 7.0.0 make `_focusMonitor` and `document` required params.
super();
if (_focusMonitor) {
diff --git a/src/lib/menu/menu-trigger.ts b/src/lib/menu/menu-trigger.ts
index 4b0f5ccff5e3..329f16abb189 100644
--- a/src/lib/menu/menu-trigger.ts
+++ b/src/lib/menu/menu-trigger.ts
@@ -90,7 +90,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
/**
* @deprecated
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
@Input('mat-menu-trigger-for')
get _deprecatedMatMenuTriggerFor(): MatMenuPanel {
@@ -113,7 +113,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
/**
* Event emitted when the associated menu is opened.
* @deprecated Switch to `menuOpened` instead
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
// tslint:disable-next-line:no-output-on-prefix
@Output() readonly onMenuOpen: EventEmitter = this.menuOpened;
@@ -124,7 +124,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
/**
* Event emitted when the associated menu is closed.
* @deprecated Switch to `menuClosed` instead
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
// tslint:disable-next-line:no-output-on-prefix
@Output() readonly onMenuClose: EventEmitter = this.menuClosed;
@@ -137,7 +137,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
@Optional() @Self() private _menuItemInstance: MatMenuItem,
@Optional() private _dir: Directionality,
// TODO(crisbeto): make the _focusMonitor required when doing breaking changes.
- // @deletion-target 7.0.0
+ // @breaking-change 7.0.0
private _focusMonitor?: FocusMonitor) {
if (_menuItemInstance) {
diff --git a/src/lib/paginator/paginator.scss b/src/lib/paginator/paginator.scss
index 1213698019fe..67e1ff2347c8 100644
--- a/src/lib/paginator/paginator.scss
+++ b/src/lib/paginator/paginator.scss
@@ -9,7 +9,7 @@ $mat-paginator-selector-trigger-width: 56px;
$mat-paginator-selector-trigger-outline-width: 64px;
$mat-paginator-selector-trigger-fill-width: 64px;
-/** @deprecated Use `$mat-paginator-selector-trigger-width` instead. @deletion-target 8.0.0 */
+/** @deprecated Use `$mat-paginator-selector-trigger-width` instead. @breaking-change 8.0.0 */
$mat-paginator-selector-trigger-min-width: $mat-paginator-selector-trigger-width;
$mat-paginator-range-actions-min-height: 48px;
diff --git a/src/lib/paginator/paginator.ts b/src/lib/paginator/paginator.ts
index 266425944efa..ee84f91c608f 100644
--- a/src/lib/paginator/paginator.ts
+++ b/src/lib/paginator/paginator.ts
@@ -35,7 +35,7 @@ export class PageEvent {
/**
* Index of the page that was selected previously.
- * @deletion-target 7.0.0 To be made into a required property.
+ * @breaking-change 7.0.0 To be made into a required property.
*/
previousPageIndex?: number;
diff --git a/src/lib/progress-bar/progress-bar.ts b/src/lib/progress-bar/progress-bar.ts
index 5124cd55b3cd..2e316531bbea 100644
--- a/src/lib/progress-bar/progress-bar.ts
+++ b/src/lib/progress-bar/progress-bar.ts
@@ -59,7 +59,7 @@ export class MatProgressBar extends _MatProgressBarMixinBase implements CanColor
@Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string,
/**
* @deprecated `location` parameter to be made required.
- * @deletion-target 8.0.0
+ * @breaking-change 8.0.0
*/
@Optional() location?: Location) {
super(_elementRef);
diff --git a/src/lib/progress-spinner/progress-spinner.ts b/src/lib/progress-spinner/progress-spinner.ts
index 2f0e6c038257..4e65b232d7f1 100644
--- a/src/lib/progress-spinner/progress-spinner.ts
+++ b/src/lib/progress-spinner/progress-spinner.ts
@@ -176,7 +176,7 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
constructor(public _elementRef: ElementRef,
platform: Platform,
@Optional() @Inject(DOCUMENT) private _document: any,
- // @deletion-target 7.0.0 animationMode and defaults parameters to be made required.
+ // @breaking-change 7.0.0 animationMode and defaults parameters to be made required.
@Optional() @Inject(ANIMATION_MODULE_TYPE) private animationMode?: string,
@Inject(MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS)
private defaults?: MatProgressSpinnerDefaultOptions) {
@@ -291,7 +291,7 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
export class MatSpinner extends MatProgressSpinner {
constructor(elementRef: ElementRef, platform: Platform,
@Optional() @Inject(DOCUMENT) document: any,
- // @deletion-targets 7.0.0 animationMode and defaults parameters to be made required.
+ // @breaking-changes 7.0.0 animationMode and defaults parameters to be made required.
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
@Inject(MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS)
defaults?: MatProgressSpinnerDefaultOptions) {
diff --git a/src/lib/select/select-animations.ts b/src/lib/select/select-animations.ts
index f08e995c45fe..8cd8376a9755 100644
--- a/src/lib/select/select-animations.ts
+++ b/src/lib/select/select-animations.ts
@@ -79,12 +79,12 @@ export const matSelectAnimations: {
/**
* @deprecated
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
export const transformPanel = matSelectAnimations.transformPanel;
/**
* @deprecated
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
export const fadeInContent = matSelectAnimations.fadeInContent;
diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts
index cd11b499f569..a81d82ebdb05 100644
--- a/src/lib/select/select.ts
+++ b/src/lib/select/select.ts
@@ -316,7 +316,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
}
/**
* @deprecated Setter to be removed as this property is intended to be readonly.
- * @deletion-target 8.0.0
+ * @breaking-change 8.0.0
*/
set focused(value: boolean) {
this._focused = value;
diff --git a/src/lib/slide-toggle/slide-toggle.ts b/src/lib/slide-toggle/slide-toggle.ts
index bb4e02cded50..ea42698e5328 100644
--- a/src/lib/slide-toggle/slide-toggle.ts
+++ b/src/lib/slide-toggle/slide-toggle.ts
@@ -185,7 +185,7 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro
constructor(elementRef: ElementRef,
/**
* @deprecated The `_platform` parameter to be removed.
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
_platform: Platform,
private _focusMonitor: FocusMonitor,
diff --git a/src/lib/slider/slider.ts b/src/lib/slider/slider.ts
index 2f3cea7be1f9..010cd84445fb 100644
--- a/src/lib/slider/slider.ts
+++ b/src/lib/slider/slider.ts
@@ -456,7 +456,7 @@ export class MatSlider extends _MatSliderMixinBase
private _changeDetectorRef: ChangeDetectorRef,
@Optional() private _dir: Directionality,
@Attribute('tabindex') tabIndex: string,
- // @deletion-target 7.0.0 `_animationMode` parameter to be made required.
+ // @breaking-change 7.0.0 `_animationMode` parameter to be made required.
@Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string) {
super(elementRef);
diff --git a/src/lib/snack-bar/snack-bar-ref.ts b/src/lib/snack-bar/snack-bar-ref.ts
index ef05f4ac7d75..60822dd149e9 100644
--- a/src/lib/snack-bar/snack-bar-ref.ts
+++ b/src/lib/snack-bar/snack-bar-ref.ts
@@ -77,7 +77,7 @@ export class MatSnackBarRef {
/**
* Marks the snackbar action clicked.
* @deprecated Use `dismissWithAction` instead.
- * @deletion-target 7.0.0
+ * @breaking-change 7.0.0
*/
closeWithAction(): void {
this.dismissWithAction();
diff --git a/src/lib/tabs/tab-body.ts b/src/lib/tabs/tab-body.ts
index 51a050d85344..8654b3ddffa6 100644
--- a/src/lib/tabs/tab-body.ts
+++ b/src/lib/tabs/tab-body.ts
@@ -156,7 +156,7 @@ export class MatTabBody implements OnInit, OnDestroy {
constructor(private _elementRef: ElementRef,
@Optional() private _dir: Directionality,
/**
- * @deletion-target 7.0.0 changeDetectorRef to be made required.
+ * @breaking-change 7.0.0 changeDetectorRef to be made required.
*/
changeDetectorRef?: ChangeDetectorRef) {
diff --git a/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts b/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts
index 35729b6b647d..f1da8e229daf 100644
--- a/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts
+++ b/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts
@@ -112,11 +112,11 @@ export class MatTabNav extends _MatTabNavMixinBase
/**
* Notifies the component that the active link has been changed.
- * @deletion-target 7.0.0 `element` parameter to be removed.
+ * @breaking-change 7.0.0 `element` parameter to be removed.
*/
updateActiveLink(element: ElementRef) {
// Note: keeping the `element` for backwards-compat, but isn't being used for anything.
- // @deletion-target 7.0.0
+ // @breaking-change 7.0.0
this._activeLinkChanged = !!element;
this._changeDetectorRef.markForCheck();
}
@@ -226,7 +226,7 @@ export class MatTabLink extends _MatTabLinkMixinBase
@Attribute('tabindex') tabIndex: string,
/**
* @deprecated
- * @deletion-target 7.0.0 `_focusMonitor` parameter to be made required.
+ * @breaking-change 7.0.0 `_focusMonitor` parameter to be made required.
*/
private _focusMonitor?: FocusMonitor) {
super();
diff --git a/src/lib/toolbar/toolbar.scss b/src/lib/toolbar/toolbar.scss
index 585e6a3a34c2..aa2e9211569f 100644
--- a/src/lib/toolbar/toolbar.scss
+++ b/src/lib/toolbar/toolbar.scss
@@ -5,9 +5,9 @@ $mat-toolbar-height-desktop: 64px !default;
$mat-toolbar-height-mobile: 56px !default;
$mat-toolbar-row-padding: 16px !default;
-/** @deprecated @deletion-target 8.0.0 */
+/** @deprecated @breaking-change 8.0.0 */
$mat-toolbar-height-mobile-portrait: 56px !default;
-/** @deprecated @deletion-target 8.0.0 */
+/** @deprecated @breaking-change 8.0.0 */
$mat-toolbar-height-mobile-landscape: 48px !default;
diff --git a/tools/dgeni/common/decorators.ts b/tools/dgeni/common/decorators.ts
index 6392f429a707..d83b6b7ea70a 100644
--- a/tools/dgeni/common/decorators.ts
+++ b/tools/dgeni/common/decorators.ts
@@ -82,14 +82,13 @@ export function hasDecorator(doc: HasDecoratorsDoc, decoratorName: string) {
doc.decorators.some(d => d.name == decoratorName);
}
-export function getDeletionTarget(doc: any): string | null {
+export function getBreakingChange(doc: any): string | null {
if (!doc.tags) {
return null;
}
- const deletionTarget = doc.tags.tags.find((t: any) => t.tagName === 'deletion-target');
-
- return deletionTarget ? deletionTarget.description : null;
+ const breakingChange = doc.tags.tags.find((t: any) => t.tagName === 'breaking-change');
+ return breakingChange ? breakingChange.description : null;
}
/**
@@ -98,12 +97,12 @@ export function getDeletionTarget(doc: any): string | null {
*/
export function decorateDeprecatedDoc(doc: DeprecationDoc) {
doc.isDeprecated = isDeprecatedDoc(doc);
- doc.deletionTarget = getDeletionTarget(doc);
+ doc.breakingChange = getBreakingChange(doc);
- if (doc.isDeprecated && !doc.deletionTarget) {
- console.warn('Warning: There is a deprecated item without a @deletion-target tag.', doc.id);
- } else if (doc.deletionTarget && !doc.isDeprecated) {
- console.warn('Warning: There is an item with a @deletion-target which is not deprecated.',
+ if (doc.isDeprecated && !doc.breakingChange) {
+ console.warn('Warning: There is a deprecated item without a @breaking-change tag.', doc.id);
+ } else if (doc.breakingChange && !doc.isDeprecated) {
+ console.warn('Warning: There is an item with a @breaking-change which is not deprecated.',
doc.id);
}
}
diff --git a/tools/dgeni/common/dgeni-definitions.ts b/tools/dgeni/common/dgeni-definitions.ts
index 63c6c85033b5..363b719677bf 100644
--- a/tools/dgeni/common/dgeni-definitions.ts
+++ b/tools/dgeni/common/dgeni-definitions.ts
@@ -8,7 +8,7 @@ import {NormalizedMethodMemberDoc} from './normalize-method-parameters';
/** Interface that describes categorized docs that can be deprecated. */
export interface DeprecationDoc extends ApiDoc {
isDeprecated: boolean;
- deletionTarget: string | null;
+ breakingChange: string | null;
}
/** Interface that describes Dgeni documents that have decorators. */
diff --git a/tools/dgeni/index.ts b/tools/dgeni/index.ts
index 87f116237380..72c3381af996 100644
--- a/tools/dgeni/index.ts
+++ b/tools/dgeni/index.ts
@@ -91,7 +91,7 @@ apiDocsPackage.config((computePathsProcessor: any) => {
apiDocsPackage.config((parseTagsProcessor: any) => {
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat([
{name: 'docs-private'},
- {name: 'deletion-target'}
+ {name: 'breaking-change'}
]);
});
diff --git a/tools/dgeni/templates/macros.html b/tools/dgeni/templates/macros.html
index 18c37f0fe952..f7369e1bb1b7 100644
--- a/tools/dgeni/templates/macros.html
+++ b/tools/dgeni/templates/macros.html
@@ -1,5 +1,5 @@
{% macro deprecationTitle(doc) %}
- {%- if doc.deletionTarget -%}
- title="Will be deleted in v{$ doc.deletionTarget $}"
+ {%- if doc.breakingChange -%}
+ title="Will be deleted in v{$ doc.breakingChange $}"
{%- endif -%}
{% endmacro %}
diff --git a/tools/tslint-rules/deletionTargetRule.ts b/tools/tslint-rules/breakingChangeRule.ts
similarity index 58%
rename from tools/tslint-rules/deletionTargetRule.ts
rename to tools/tslint-rules/breakingChangeRule.ts
index 18a462b76338..79e547733117 100644
--- a/tools/tslint-rules/deletionTargetRule.ts
+++ b/tools/tslint-rules/breakingChangeRule.ts
@@ -3,8 +3,14 @@ import * as Lint from 'tslint';
import * as utils from 'tsutils';
import * as path from 'path';
+/** Doc tag that can be used to indicate a breaking change. */
+const BREAKING_CHANGE = '@breaking-change';
+
+/** Name of the old doc tag that was being used to indicate a breaking change. */
+const DELETION_TARGET = '@deletion-target';
+
/**
- * Rule ensuring that deletion targets have not expired.
+ * Rule ensuring that breaking changes have not expired.
* The current version is taken from the `package.json`.
*/
export class Rule extends Lint.Rules.AbstractRule {
@@ -15,17 +21,25 @@ export class Rule extends Lint.Rules.AbstractRule {
return this.applyWithFunction(sourceFile, (ctx: Lint.WalkContext) => {
utils.forEachComment(ctx.sourceFile, (file, {pos, end}) => {
const commentText = file.substring(pos, end);
- const hasDeletionTarget = commentText.indexOf('@deletion-target') > -1;
- if (!hasDeletionTarget && commentText.indexOf('@deprecated') > -1) {
- ctx.addFailure(pos, end, '@deprecated marker has to have a @deletion-target.');
- } if (hasDeletionTarget) {
+ // TODO(crisbeto): remove this check once most of the pending
+ // PRs start using `breaking-change`.
+ if (commentText.indexOf(DELETION_TARGET) > -1) {
+ ctx.addFailure(pos, end, `${DELETION_TARGET} has been replaced with ${BREAKING_CHANGE}.`);
+ return;
+ }
+
+ const hasBreakingChange = commentText.indexOf(BREAKING_CHANGE) > -1;
+
+ if (!hasBreakingChange && commentText.indexOf('@deprecated') > -1) {
+ ctx.addFailure(pos, end, `@deprecated marker has to have a ${BREAKING_CHANGE}.`);
+ } if (hasBreakingChange) {
const version = commentText.match(/\d+\.\d+\.\d+/);
if (!version) {
- ctx.addFailure(pos, end, '@deletion-target must have a version.');
+ ctx.addFailure(pos, end, `${BREAKING_CHANGE} must have a version.`);
} else if (this._hasExpired(packageVersion, version[0])) {
- ctx.addFailure(pos, end, `Deletion target at ${version[0]} is due to be deleted. ` +
+ ctx.addFailure(pos, end, `Breaking change at ${version[0]} is due to be deleted. ` +
`Current version is ${packageVersion}.`);
}
}
@@ -36,15 +50,15 @@ export class Rule extends Lint.Rules.AbstractRule {
/**
* Checks whether a version has expired, based on the current version.
* @param currentVersion Current version of the package.
- * @param deletionTarget Version that is being checked.
+ * @param breakingChange Version that is being checked.
*/
- private _hasExpired(currentVersion: string, deletionTarget: string) {
- if (currentVersion === deletionTarget) {
+ private _hasExpired(currentVersion: string, breakingChange: string) {
+ if (currentVersion === breakingChange) {
return true;
}
const current = this._parseVersion(currentVersion);
- const target = this._parseVersion(deletionTarget);
+ const target = this._parseVersion(breakingChange);
return target.major < current.major ||
(target.major === current.major && target.minor < current.minor) ||
diff --git a/tslint.json b/tslint.json
index ff30b9385e50..e6576b790451 100644
--- a/tslint.json
+++ b/tslint.json
@@ -126,7 +126,7 @@
"./tools/package-tools/rollup-globals.ts",
"src/+(lib|cdk|material-examples|material-experimental|cdk-experimental)/**/*.ts"
],
- "deletion-target": true,
+ "breaking-change": true,
"no-unescaped-html-tag": true
},
"linterOptions": {
From f84823c0aaec379b87c3cbdc6509caec5cea0907 Mon Sep 17 00:00:00 2001
From: mmalerba
Date: Mon, 30 Jul 2018 15:01:02 -0700
Subject: [PATCH 052/189] chore: 6.4.2 changelog (#12441)
* chore: 6.4.2 changelog
* address comments
---
CHANGELOG.md | 20 ++++++++++++++++++++
package.json | 2 +-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb43956141a6..9a04bcfcc699 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+
+## [6.4.2 chalk-window](https://github.com/angular/material2/compare/6.4.1...6.4.2) (2018-07-30)
+
+
+### Bug Fixes
+
+* **autocomplete:** remove aria-owns attribute while closed ([#12333](https://github.com/angular/material2/issues/12333)) ([2122b18](https://github.com/angular/material2/commit/2122b18)), closes [#12332](https://github.com/angular/material2/issues/12332)
+* **card:** incorrectly inverting inset divider in rtl ([#12285](https://github.com/angular/material2/issues/12285)) ([8a2dc60](https://github.com/angular/material2/commit/8a2dc60))
+* **progress-bar:** query animation not working inside routes with named outlets ([#12350](https://github.com/angular/material2/issues/12350)) ([0c526d3](https://github.com/angular/material2/commit/0c526d3)), closes [#12014](https://github.com/angular/material2/issues/12014) [#12338](https://github.com/angular/material2/issues/12338)
+* **snack-bar:** prevent content from overriding configured aria-live message ([#12294](https://github.com/angular/material2/issues/12294)) ([b46689e](https://github.com/angular/material2/commit/b46689e))
+* **ng-update:** support parenthesized directive metadata ([#12314](https://github.com/angular/material2/issues/12314)) ([66416f5](https://github.com/angular/material2/commit/66416f5))
+
+
+### Performance Improvements
+
+* **table:** leaking reference through mostRecentCellOutlet ([#12269](https://github.com/angular/material2/issues/12269)) ([7c8e892](https://github.com/angular/material2/commit/7c8e892)), closes [#12259](https://github.com/angular/material2/issues/12259)
+* **tree:** leaking reference through mostRecentTreeNode ([#12334](https://github.com/angular/material2/issues/12334)) ([b6f7205](https://github.com/angular/material2/commit/b6f7205)), closes [#12269](https://github.com/angular/material2/issues/12269)
+
+
+
## [6.4.1 elm-electrode](https://github.com/angular/material2/compare/6.4.0...6.4.1) (2018-07-23)
diff --git a/package.json b/package.json
index 69ce4c061948..2e9575fe59ea 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"docs": "gulp docs",
"api": "gulp api-docs"
},
- "version": "6.4.1",
+ "version": "6.4.2",
"license": "MIT",
"engines": {
"node": ">= 5.4.1"
From ee635187f8ae874b52fbd62e2a472de712451015 Mon Sep 17 00:00:00 2001
From: mmalerba
Date: Tue, 31 Jul 2018 09:03:53 -0700
Subject: [PATCH 053/189] chore: use regex to whitelist branches for CI
(#12439)
---
.circleci/config.yml | 4 ++++
.travis.yml | 11 ++++-------
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index f8f7f672a9b0..27a9650c14c9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -69,3 +69,7 @@ general:
branches:
only:
- master
+ # 5.2.x, 6.0.x, etc
+ - /\d+\.\d+\.x/
+ # 5.x, 6.x, etc
+ - /\d+\.x/
diff --git a/.travis.yml b/.travis.yml
index 53b314e17c21..98c74158b1e1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,13 +18,10 @@ addons:
branches:
only:
- master
- - 5.0.x
- - 5.1.x
- - 5.2.x
- - 6.0.x
- - 6.1.x
- - 6.2.x
- - 6.3.x
+ # 5.2.x, 6.0.x, etc
+ - /\d+\.\d+\.x/
+ # 5.x, 6.x, etc
+ - /\d+\.x/
jobs:
include:
From 390afa34ca68aea59a7587564938a74f0a4a2d16 Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Tue, 31 Jul 2018 18:23:20 +0200
Subject: [PATCH 054/189] build: add version stamp to release output (#12418)
---
tools/gulp/tasks/publish.ts | 5 ++-
tools/gulp/tasks/validate-release.ts | 20 +++++++++-
tools/package-tools/build-release.ts | 3 ++
tools/package-tools/package-version-stamp.ts | 42 ++++++++++++++++++++
4 files changed, 67 insertions(+), 3 deletions(-)
create mode 100644 tools/package-tools/package-version-stamp.ts
diff --git a/tools/gulp/tasks/publish.ts b/tools/gulp/tasks/publish.ts
index 6c65a3eb666f..0cf92199b6d0 100644
--- a/tools/gulp/tasks/publish.ts
+++ b/tools/gulp/tasks/publish.ts
@@ -25,6 +25,7 @@ const argv = minimist(process.argv.slice(3));
task('publish', sequenceTask(
':publish:whoami',
':publish:build-releases',
+ 'validate-release:check-remote-tag',
'validate-release:check-bundles',
':publish',
':publish:logout',
@@ -52,8 +53,8 @@ task(':publish', async () => {
if (!version.match(validVersionRegex)) {
console.log(red(`Error: Cannot publish due to an invalid version name. Version "${version}" ` +
`is not following our semver format.`));
- console.log(yellow(`A version should follow this format: d.d.d, d.d.d-beta.x, d.d.d-alpha.x, ` +
- `d.d.d-rc.x`));
+ console.log(yellow(`A version should follow this format: X.X.X, X.X.X-beta.X, X.X.X-alpha.X, ` +
+ `X.X.X-rc.X`));
return;
}
diff --git a/tools/gulp/tasks/validate-release.ts b/tools/gulp/tasks/validate-release.ts
index 1c8a266865a2..b6ba651401a7 100644
--- a/tools/gulp/tasks/validate-release.ts
+++ b/tools/gulp/tasks/validate-release.ts
@@ -4,10 +4,16 @@ import {join} from 'path';
import {green, red} from 'chalk';
import {releasePackages} from './publish';
import {sync as glob} from 'glob';
+import {spawnSync} from 'child_process';
import {buildConfig, sequenceTask} from 'material2-build-tools';
+const {projectDir, projectVersion, outputDir} = buildConfig;
+
+/** Git repository URL that has been read out from the project package.json file. */
+const repositoryGitUrl = require('../../../package.json').repository.url;
+
/** Path to the directory where all releases are created. */
-const releasesDir = join(buildConfig.outputDir, 'releases');
+const releasesDir = join(outputDir, 'releases');
/** RegExp that matches Angular component inline styles that contain a sourcemap reference. */
const inlineStylesSourcemapRegex = /styles: ?\[["'].*sourceMappingURL=.*["']/;
@@ -17,6 +23,18 @@ const externalReferencesRegex = /(templateUrl|styleUrls): *["'[]/;
task('validate-release', sequenceTask(':publish:build-releases', 'validate-release:check-bundles'));
+task('validate-release:check-remote-tag', () => {
+ // Since we cannot assume that every developer uses `origin` as the default name for the upstream
+ // remote, we just pass in the Git URL that refers to angular/material2 repository on Github.
+ const tagCommitSha = spawnSync('git', ['ls-remote', '--tags', repositoryGitUrl, projectVersion],
+ {cwd: projectDir}).stdout.toString().trim();
+
+ if (!tagCommitSha) {
+ throw Error(red(`Cannot publish v${projectVersion} because the release is not ` +
+ `tagged on upstream yet. Please tag the release before publishing to NPM.`));
+ }
+});
+
/** Task that checks the release bundles for any common mistakes before releasing to the public. */
task('validate-release:check-bundles', () => {
const releaseFailures = releasePackages
diff --git a/tools/package-tools/build-release.ts b/tools/package-tools/build-release.ts
index f3fc35f3dff6..1f44b1f4b6b4 100644
--- a/tools/package-tools/build-release.ts
+++ b/tools/package-tools/build-release.ts
@@ -7,6 +7,7 @@ import {copyFiles} from './copy-files';
import {createEntryPointPackageJson} from './entry-point-package-json';
import {inlinePackageMetadataFiles} from './metadata-inlining';
import {createMetadataReexportFile} from './metadata-reexport';
+import {insertPackageJsonVersionStamp} from './package-version-stamp';
import {createTypingsReexportFile} from './typings-reexport';
import {replaceVersionPlaceholders} from './version-placeholders';
@@ -48,6 +49,8 @@ export function composeRelease(buildPackage: BuildPackage) {
copyFiles(sourceDir, 'package.json', releasePath);
replaceVersionPlaceholders(releasePath);
+ insertPackageJsonVersionStamp(join(releasePath, 'package.json'));
+
createTypingsReexportFile(releasePath, './typings/index', name);
createMetadataReexportFile(releasePath, './typings/index', name, importAsName);
diff --git a/tools/package-tools/package-version-stamp.ts b/tools/package-tools/package-version-stamp.ts
new file mode 100644
index 000000000000..fab20422f7a3
--- /dev/null
+++ b/tools/package-tools/package-version-stamp.ts
@@ -0,0 +1,42 @@
+import {writeFileSync} from 'fs';
+import {spawnSync} from 'child_process';
+import {buildConfig} from './build-config';
+
+/**
+ * Inserts the a version stamp, which consists of the current commit SHA and the current
+ * branch name, into the specified package.json file.
+ *
+ * This makes it easy to quickly verify the exact snapshot from which the release originated.
+ */
+export function insertPackageJsonVersionStamp(packageJsonPath: string) {
+ const packageJson = require(packageJsonPath);
+
+ packageJson['releaseGitCommitSha'] = getCurrentCommitSha();
+ packageJson['releaseGitBranch'] = getCurrentBranchName();
+ packageJson['releaseGitUser'] = getCurrentGitUser();
+
+ writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
+}
+
+/** Returns the commit SHA for the current git HEAD of the project. */
+function getCurrentCommitSha(): string {
+ return spawnSync('git', ['rev-parse', 'HEAD'], {cwd: buildConfig.projectDir})
+ .stdout.toString().trim();
+}
+
+/** Returns the name of the currently checked out branch of the project. */
+function getCurrentBranchName(): string {
+ return spawnSync('git', ['symbolic-ref', '--short', 'HEAD'], {cwd: buildConfig.projectDir})
+ .stdout.toString().trim();
+}
+
+/** Returns the name and email of the Git user that creates this release build. */
+function getCurrentGitUser() {
+ const userName = spawnSync('git', ['config', 'user.name'], {cwd: buildConfig.projectDir})
+ .stdout.toString().trim();
+
+ const userEmail = spawnSync('git', ['config', 'user.email'], {cwd: buildConfig.projectDir})
+ .stdout.toString().trim();
+
+ return `${userName} <${userEmail}>`;
+}
From 3580fb53931950c6c2ac84fcd34b8d8569203950 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:03:57 +0200
Subject: [PATCH 055/189] fix(drag-drop): account for transition-delay when
waiting for the animation to finish (#12466)
Currently we have some functionality that waits for the preview's animation to finish and falls back to a timeout, based on the computed `transition-duration`, however that fallback doesn't account for the case where the element has a `transition-delay`. These changes account for the delay.
---
src/cdk-experimental/drag-drop/drag.ts | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/src/cdk-experimental/drag-drop/drag.ts b/src/cdk-experimental/drag-drop/drag.ts
index b4a5d47591d3..b6d7f3ee9328 100644
--- a/src/cdk-experimental/drag-drop/drag.ts
+++ b/src/cdk-experimental/drag-drop/drag.ts
@@ -462,7 +462,7 @@ export class CdkDrag implements OnDestroy {
// we need to trigger a style recalculation in order for the `cdk-drag-animating` class to
// apply its style, we take advantage of the available info to figure out whether we need to
// bind the event in the first place.
- const duration = this._getTransitionDurationInMs(this._preview);
+ const duration = getTransitionDurationInMs(this._preview);
if (duration === 0) {
return Promise.resolve();
@@ -547,17 +547,25 @@ export class CdkDrag implements OnDestroy {
this._placeholder = this._placeholderRef = null!;
}
+}
- /** Gets the `transition-duration` of an element in milliseconds. */
- private _getTransitionDurationInMs(element: HTMLElement): number {
- const rawDuration = getComputedStyle(element).getPropertyValue('transition-duration');
+/** Parses a CSS time value to milliseconds. */
+function parseCssTimeUnitsToMs(value: string): number {
+ // Some browsers will return it in seconds, whereas others will return milliseconds.
+ const multiplier = value.toLowerCase().indexOf('ms') > -1 ? 1 : 1000;
+ return parseFloat(value) * multiplier;
+}
- // Some browsers will return it in seconds, whereas others will return milliseconds.
- const multiplier = rawDuration.toLowerCase().indexOf('ms') > -1 ? 1 : 1000;
- return parseFloat(rawDuration) * multiplier;
- }
+/** Gets the transition duration, including the delay, of an element in milliseconds. */
+function getTransitionDurationInMs(element: HTMLElement): number {
+ const computedStyle = getComputedStyle(element);
+ const rawDuration = computedStyle.getPropertyValue('transition-duration');
+ const rawDelay = computedStyle.getPropertyValue('transition-delay');
+
+ return parseCssTimeUnitsToMs(rawDuration) + parseCssTimeUnitsToMs(rawDelay);
}
+
/** Point on the page or within an element. */
interface Point {
x: number;
From 212bd0b2c4c6f852a2c3d80463dfa36e0734044c Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:14:00 +0200
Subject: [PATCH 056/189] fix(form-field): unable to distinguish disabled form
field in high contrast mode (#12445)
Fixes the disabled form field being indistinguishable from enabled ones in high contrast mode, due to the dotted gradient not being rendered.
---
src/lib/form-field/form-field-legacy.scss | 5 +++++
src/lib/form-field/form-field-standard.scss | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/src/lib/form-field/form-field-legacy.scss b/src/lib/form-field/form-field-legacy.scss
index f0be9791b866..77344f0999f6 100644
--- a/src/lib/form-field/form-field-legacy.scss
+++ b/src/lib/form-field/form-field-legacy.scss
@@ -58,6 +58,11 @@ $mat-form-field-legacy-underline-height: 1px !default;
&.mat-form-field-disabled .mat-form-field-underline {
background-position: 0;
background-color: transparent;
+
+ @include cdk-high-contrast {
+ border-top-style: dotted;
+ border-top-width: 2px;
+ }
}
&.mat-form-field-invalid:not(.mat-focused) .mat-form-field-ripple {
diff --git a/src/lib/form-field/form-field-standard.scss b/src/lib/form-field/form-field-standard.scss
index 4910f3efa458..16a8ce349c9f 100644
--- a/src/lib/form-field/form-field-standard.scss
+++ b/src/lib/form-field/form-field-standard.scss
@@ -42,6 +42,11 @@ $mat-form-field-standard-padding-top: 0.75em !default;
&.mat-form-field-disabled .mat-form-field-underline {
background-position: 0;
background-color: transparent;
+
+ @include cdk-high-contrast {
+ border-top-style: dotted;
+ border-top-width: 2px;
+ }
}
// Note that we need this specific of a selector because we don't want
From 3652707b6018bf50c8c17fe2a4d301fdede694b8 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:14:14 +0200
Subject: [PATCH 057/189] fix(chips): focus indication not visible in high
contrast mode (#12431)
Fixes not being able to tell which chip is focused in high contrast mode.
---
src/lib/chips/chips.scss | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/lib/chips/chips.scss b/src/lib/chips/chips.scss
index e8f64f303d6b..235a078da4fd 100644
--- a/src/lib/chips/chips.scss
+++ b/src/lib/chips/chips.scss
@@ -47,6 +47,11 @@ $mat-chip-remove-size: 18px;
@include cdk-high-contrast {
outline: solid 1px;
+
+ &:focus {
+ // Use 2px here since the dotted outline is a little thinner.
+ outline: dotted 2px;
+ }
}
&.mat-chip-with-trailing-icon.mat-chip-with-avatar,
From 5053532b1214024fff4decbeff42270879650926 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:15:00 +0200
Subject: [PATCH 058/189] fix(chips): dynamic chip input placeholder changes
not being propagated to form field (#12422)
Fixes changes to the placeholder of a chip input not being propagated to its parent form field. Also un-deprecates the input for `placeholder`, because we need to know when it has changed.
Fixes #11861.
---
src/lib/chips/chip-input.spec.ts | 36 +++++++++++++++++++++++++-------
src/lib/chips/chip-input.ts | 14 ++++++-------
2 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/src/lib/chips/chip-input.spec.ts b/src/lib/chips/chip-input.spec.ts
index c8ba72cf6263..35af7f394d31 100644
--- a/src/lib/chips/chip-input.spec.ts
+++ b/src/lib/chips/chip-input.spec.ts
@@ -5,6 +5,8 @@ import {createKeyboardEvent} from '@angular/cdk/testing';
import {Component, DebugElement} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
+import {NoopAnimationsModule} from '@angular/platform-browser/animations';
+import {MatFormFieldModule} from '@angular/material/form-field';
import {MatChipInput, MatChipInputEvent} from './chip-input';
import {MatChipsModule} from './index';
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
@@ -20,7 +22,7 @@ describe('MatChipInput', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- imports: [MatChipsModule, PlatformModule],
+ imports: [PlatformModule, MatChipsModule, MatFormFieldModule, NoopAnimationsModule],
declarations: [TestChipInput],
providers: [{
provide: Directionality, useFactory: () => {
@@ -64,6 +66,22 @@ describe('MatChipInput', () => {
expect(inputNativeElement.getAttribute('placeholder')).toBe('bound placeholder');
});
+
+ it('should propagate the dynamic `placeholder` value to the form field', () => {
+ fixture.componentInstance.placeholder = 'add a chip';
+ fixture.detectChanges();
+
+ const label: HTMLElement = fixture.nativeElement.querySelector('.mat-form-field-label');
+
+ expect(label).toBeTruthy();
+ expect(label.textContent).toContain('add a chip');
+
+ fixture.componentInstance.placeholder = 'or don\'t';
+ fixture.detectChanges();
+
+ expect(label.textContent).toContain('or don\'t');
+ });
+
});
describe('[addOnBlur]', () => {
@@ -117,7 +135,7 @@ describe('MatChipInput', () => {
TestBed
.resetTestingModule()
.configureTestingModule({
- imports: [MatChipsModule, PlatformModule],
+ imports: [MatChipsModule, MatFormFieldModule, PlatformModule, NoopAnimationsModule],
declarations: [TestChipInput],
providers: [{
provide: MAT_CHIPS_DEFAULT_OPTIONS,
@@ -146,12 +164,14 @@ describe('MatChipInput', () => {
@Component({
template: `
-
-
-
+
+
+
+
+
`
})
class TestChipInput {
diff --git a/src/lib/chips/chip-input.ts b/src/lib/chips/chip-input.ts
index fa7249bfb53a..50570fc4b091 100644
--- a/src/lib/chips/chip-input.ts
+++ b/src/lib/chips/chip-input.ts
@@ -7,7 +7,7 @@
*/
import {coerceBooleanProperty} from '@angular/cdk/coercion';
-import {Directive, ElementRef, EventEmitter, Input, Output, Inject} from '@angular/core';
+import {Directive, ElementRef, EventEmitter, Input, Output, Inject, OnChanges} from '@angular/core';
import {MatChipList} from './chip-list';
import {MAT_CHIPS_DEFAULT_OPTIONS, MatChipsDefaultOptions} from './chip-default-options';
@@ -41,7 +41,7 @@ let nextUniqueId = 0;
'[attr.placeholder]': 'placeholder || null',
}
})
-export class MatChipInput {
+export class MatChipInput implements OnChanges {
/** Whether the control is focused. */
focused: boolean = false;
_chipList: MatChipList;
@@ -76,11 +76,7 @@ export class MatChipInput {
@Output('matChipInputTokenEnd')
chipEnd: EventEmitter = new EventEmitter();
- /**
- * The input's placeholder text.
- * @deprecated Bind to the `placeholder` attribute directly.
- * @breaking-change 7.0.0
- */
+ /** The input's placeholder text. */
@Input() placeholder: string = '';
/** Unique id for the input. */
@@ -98,6 +94,10 @@ export class MatChipInput {
this._inputElement = this._elementRef.nativeElement as HTMLInputElement;
}
+ ngOnChanges() {
+ this._chipList.stateChanges.next();
+ }
+
/** Utility method to make host definition/tests more clear. */
_keydown(event?: KeyboardEvent) {
this._emitChipEnd(event);
From 40d8ae4e348a5e52d8083dee1b6bf9dc86c31346 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:15:23 +0200
Subject: [PATCH 059/189] perf(overlay): remove detached overlays from the DOM
(#12414)
Removes the detached overlays from the DOM, rather than keeping their host element. Previously we kept the elements in the DOM, because they don't interfere with user interactions and it made it easier to handle animations, however doing so can cause scroll jank, because the host still has dimensions and is being rendered by the browser.
Fixes #12341.
---
src/cdk/overlay/overlay-directives.spec.ts | 4 --
src/cdk/overlay/overlay-ref.ts | 36 +++++++++++++--
src/cdk/overlay/overlay.spec.ts | 54 ++++++++++++++++++----
src/lib/tooltip/tooltip.spec.ts | 9 ++--
4 files changed, 84 insertions(+), 19 deletions(-)
diff --git a/src/cdk/overlay/overlay-directives.spec.ts b/src/cdk/overlay/overlay-directives.spec.ts
index 875a0a16ecc2..685052565e40 100644
--- a/src/cdk/overlay/overlay-directives.spec.ts
+++ b/src/cdk/overlay/overlay-directives.spec.ts
@@ -51,15 +51,11 @@ describe('Overlay directives', () => {
fixture.detectChanges();
expect(overlayContainerElement.textContent).toContain('Menu content');
- expect(getPaneElement().style.pointerEvents)
- .toBe('auto', 'Expected the overlay pane to enable pointerEvents when attached.');
fixture.componentInstance.isOpen = false;
fixture.detectChanges();
expect(overlayContainerElement.textContent).toBe('');
- expect(getPaneElement().style.pointerEvents)
- .toBe('none', 'Expected the overlay pane to disable pointerEvents when detached.');
});
it('should destroy the overlay when the directive is destroyed', () => {
diff --git a/src/cdk/overlay/overlay-ref.ts b/src/cdk/overlay/overlay-ref.ts
index 3ff749565ed8..e0bfeceb593d 100644
--- a/src/cdk/overlay/overlay-ref.ts
+++ b/src/cdk/overlay/overlay-ref.ts
@@ -9,8 +9,8 @@
import {Direction, Directionality} from '@angular/cdk/bidi';
import {ComponentPortal, Portal, PortalOutlet, TemplatePortal} from '@angular/cdk/portal';
import {ComponentRef, EmbeddedViewRef, NgZone} from '@angular/core';
-import {Observable, Subject} from 'rxjs';
-import {take} from 'rxjs/operators';
+import {Observable, Subject, merge} from 'rxjs';
+import {take, takeUntil} from 'rxjs/operators';
import {OverlayKeyboardDispatcher} from './keyboard/overlay-keyboard-dispatcher';
import {OverlayConfig} from './overlay-config';
import {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion';
@@ -31,6 +31,12 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
private _backdropClick: Subject = new Subject();
private _attachments = new Subject();
private _detachments = new Subject();
+
+ /**
+ * Reference to the parent of the `_host` at the time it was detached. Used to restore
+ * the `_host` to its original position in the DOM when it gets re-attached.
+ */
+ private _previousHostParent: HTMLElement;
private _keydownEventsObservable: Observable = Observable.create(observer => {
const subscription = this._keydownEvents.subscribe(observer);
this._keydownEventSubscriptions++;
@@ -99,6 +105,10 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
}
// Update the pane element with the given configuration.
+ if (!this._host.parentElement && this._previousHostParent) {
+ this._previousHostParent.appendChild(this._host);
+ }
+
this._updateStackingOrder();
this._updateElementSize();
this._updateElementDirection();
@@ -176,6 +186,26 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
// Remove this overlay from keyboard dispatcher tracking.
this._keyboardDispatcher.remove(this);
+ // Keeping the host element in DOM the can cause scroll jank, because it still gets rendered,
+ // even though it's transparent and unclickable. We can't remove the host here immediately,
+ // because the overlay pane's content might still be animating. This stream helps us avoid
+ // interrupting the animation by waiting for the pane to become empty.
+ const subscription = this._ngZone.onStable
+ .asObservable()
+ .pipe(takeUntil(merge(this._attachments, this._detachments)))
+ .subscribe(() => {
+ // Needs a couple of checks for the pane and host, because
+ // they may have been removed by the time the zone stabilizes.
+ if (!this._pane || !this._host || this._pane.children.length === 0) {
+ if (this._host && this._host.parentElement) {
+ this._previousHostParent = this._host.parentElement;
+ this._previousHostParent.removeChild(this._host);
+ }
+
+ subscription.unsubscribe();
+ }
+ });
+
return detachmentResult;
}
@@ -203,7 +233,7 @@ export class OverlayRef implements PortalOutlet, OverlayReference {
this._host = null!;
}
- this._pane = null!;
+ this._previousHostParent = this._pane = null!;
if (isAttached) {
this._detachments.next();
diff --git a/src/cdk/overlay/overlay.spec.ts b/src/cdk/overlay/overlay.spec.ts
index bde5039aaf3e..05f944422ee1 100644
--- a/src/cdk/overlay/overlay.spec.ts
+++ b/src/cdk/overlay/overlay.spec.ts
@@ -7,9 +7,10 @@ import {
ErrorHandler,
Injectable,
EventEmitter,
+ NgZone,
} from '@angular/core';
import {Direction, Directionality} from '@angular/cdk/bidi';
-import {dispatchFakeEvent} from '@angular/cdk/testing';
+import {dispatchFakeEvent, MockNgZone} from '@angular/cdk/testing';
import {
ComponentPortal,
PortalModule,
@@ -35,19 +36,26 @@ describe('Overlay', () => {
let overlayContainer: OverlayContainer;
let viewContainerFixture: ComponentFixture;
let dir: Direction;
+ let zone: MockNgZone;
beforeEach(async(() => {
dir = 'ltr';
TestBed.configureTestingModule({
imports: [OverlayModule, PortalModule, OverlayTestModule],
- providers: [{
- provide: Directionality,
- useFactory: () => {
- const fakeDirectionality = {};
- Object.defineProperty(fakeDirectionality, 'value', {get: () => dir});
- return fakeDirectionality;
- }
- }],
+ providers: [
+ {
+ provide: Directionality,
+ useFactory: () => {
+ const fakeDirectionality = {};
+ Object.defineProperty(fakeDirectionality, 'value', {get: () => dir});
+ return fakeDirectionality;
+ }
+ },
+ {
+ provide: NgZone,
+ useFactory: () => zone = new MockNgZone()
+ },
+ ],
}).compileComponents();
}));
@@ -342,6 +350,33 @@ describe('Overlay', () => {
expect(overlayRef.getDirection()).toBe('ltr');
});
+ it('should add and remove the overlay host as the ref is being attached and detached', () => {
+ const overlayRef = overlay.create();
+
+ overlayRef.attach(componentPortal);
+ viewContainerFixture.detectChanges();
+
+ expect(overlayRef.hostElement.parentElement)
+ .toBeTruthy('Expected host element to be in the DOM.');
+
+ overlayRef.detach();
+
+ expect(overlayRef.hostElement.parentElement)
+ .toBeTruthy('Expected host element not to have been removed immediately.');
+
+ viewContainerFixture.detectChanges();
+ zone.simulateZoneExit();
+
+ expect(overlayRef.hostElement.parentElement)
+ .toBeFalsy('Expected host element to have been removed once the zone stabilizes.');
+
+ overlayRef.attach(componentPortal);
+ viewContainerFixture.detectChanges();
+
+ expect(overlayRef.hostElement.parentElement)
+ .toBeTruthy('Expected host element to be back in the DOM.');
+ });
+
describe('positioning', () => {
let config: OverlayConfig;
@@ -354,6 +389,7 @@ describe('Overlay', () => {
overlay.create(config).attach(componentPortal);
viewContainerFixture.detectChanges();
+ zone.simulateZoneExit();
tick();
expect(overlayContainerElement.querySelectorAll('.fake-positioned').length).toBe(1);
diff --git a/src/lib/tooltip/tooltip.spec.ts b/src/lib/tooltip/tooltip.spec.ts
index 64f7cb3c6dd1..25bea8c35488 100644
--- a/src/lib/tooltip/tooltip.spec.ts
+++ b/src/lib/tooltip/tooltip.spec.ts
@@ -512,21 +512,24 @@ describe('MatTooltip', () => {
it('should keep the overlay direction in sync with the trigger direction', fakeAsync(() => {
dir.value = 'rtl';
tooltipDirective.show();
- tick();
+ tick(0);
fixture.detectChanges();
+ tick(500);
let tooltipWrapper =
overlayContainerElement.querySelector('.cdk-overlay-connected-position-bounding-box')!;
expect(tooltipWrapper.getAttribute('dir')).toBe('rtl', 'Expected tooltip to be in RTL.');
tooltipDirective.hide(0);
- tick();
+ tick(0);
fixture.detectChanges();
+ tick(500);
dir.value = 'ltr';
tooltipDirective.show();
- tick();
+ tick(0);
fixture.detectChanges();
+ tick(500);
tooltipWrapper =
overlayContainerElement.querySelector('.cdk-overlay-connected-position-bounding-box')!;
From 952b553c6862d205f09b927674f41f4ebdc3da3f Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:17:20 +0200
Subject: [PATCH 060/189] fix(form-field): reset inputs not being reset on
safari (#12413)
Fixes Safari's custom styling for `input[type='search']` not being reset inside of form fields.
Fixes #12408.
---
src/lib/input/input.scss | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/lib/input/input.scss b/src/lib/input/input.scss
index f18496a15066..87d6581753f6 100644
--- a/src/lib/input/input.scss
+++ b/src/lib/input/input.scss
@@ -43,6 +43,15 @@
display: none;
}
+ // Clear Safari's decorations for search fields.
+ &,
+ &::-webkit-search-cancel-button,
+ &::-webkit-search-decoration,
+ &::-webkit-search-results-button,
+ &::-webkit-search-results-decoration {
+ -webkit-appearance: none;
+ }
+
// Also clear Safari's autofill icons. Note that this can't be in the
// same selector as the IE ones, otherwise Safari will ignore it.
&::-webkit-contacts-auto-fill-button,
From 58361f1e6813e6cf1712af35540bf779374c706b Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:18:01 +0200
Subject: [PATCH 061/189] fix(bidi): default invalid directionality values to
ltr (#12396)
Fixes invalid directionality values being accepted as they are, rather than defaulting to ltr. Browsers fall back to ltr anyway, however having an invalid value can break some of our component that could be checking for one of the correct values explicitly.
---
src/cdk/bidi/dir.ts | 4 ++--
src/cdk/bidi/directionality.spec.ts | 25 +++++++++++++++++++++++--
src/cdk/bidi/directionality.ts | 3 ++-
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/src/cdk/bidi/dir.ts b/src/cdk/bidi/dir.ts
index f5fe1230a839..dbf246361376 100644
--- a/src/cdk/bidi/dir.ts
+++ b/src/cdk/bidi/dir.ts
@@ -41,9 +41,9 @@ export class Dir implements Directionality, AfterContentInit, OnDestroy {
/** @docs-private */
@Input()
get dir(): Direction { return this._dir; }
- set dir(v: Direction) {
+ set dir(value: Direction) {
const old = this._dir;
- this._dir = v;
+ this._dir = (value === 'ltr' || value === 'rtl') ? value : 'ltr';
if (old !== this._dir && this._isInitialized) {
this.change.emit(this._dir);
}
diff --git a/src/cdk/bidi/directionality.spec.ts b/src/cdk/bidi/directionality.spec.ts
index 7451d3247ba9..89414a81859b 100644
--- a/src/cdk/bidi/directionality.spec.ts
+++ b/src/cdk/bidi/directionality.spec.ts
@@ -1,7 +1,7 @@
import {async, fakeAsync, TestBed} from '@angular/core/testing';
-import {Component} from '@angular/core';
+import {Component, ViewChild} from '@angular/core';
import {By} from '@angular/platform-browser';
-import {BidiModule, Directionality, Direction, DIR_DOCUMENT} from './index';
+import {BidiModule, Directionality, Dir, Direction, DIR_DOCUMENT} from './index';
describe('Directionality', () => {
let fakeDocument: FakeDocument;
@@ -55,6 +55,15 @@ describe('Directionality', () => {
subscription.unsubscribe();
});
+ it('should default to ltr if an invalid direction is set on the body', () => {
+ fakeDocument.body.dir = 'not-valid';
+
+ const fixture = TestBed.createComponent(InjectsDirectionality);
+ const testComponent = fixture.debugElement.componentInstance;
+
+ expect(testComponent.dir.value).toBe('ltr');
+ });
+
});
describe('Dir directive', () => {
@@ -103,6 +112,17 @@ describe('Directionality', () => {
subscription.unsubscribe();
}));
+ it('should default to ltr if an invalid value is passed in', () => {
+ const fixture = TestBed.createComponent(ElementWithDir);
+
+ fixture.detectChanges();
+ expect(fixture.componentInstance.dir.value).toBe('rtl');
+
+ fixture.componentInstance.direction = 'not-valid';
+ fixture.detectChanges();
+ expect(fixture.componentInstance.dir.value).toBe('ltr');
+ });
+
});
});
@@ -115,6 +135,7 @@ describe('Directionality', () => {
`
})
class ElementWithDir {
+ @ViewChild(Dir) dir: Dir;
direction = 'rtl';
changeCount = 0;
}
diff --git a/src/cdk/bidi/directionality.ts b/src/cdk/bidi/directionality.ts
index 88a5c068d9eb..1c95de0109f8 100644
--- a/src/cdk/bidi/directionality.ts
+++ b/src/cdk/bidi/directionality.ts
@@ -33,7 +33,8 @@ export class Directionality implements OnDestroy {
// but getComputedStyle return either "ltr" or "rtl". avoiding getComputedStyle for now
const bodyDir = _document.body ? _document.body.dir : null;
const htmlDir = _document.documentElement ? _document.documentElement.dir : null;
- this.value = (bodyDir || htmlDir || 'ltr') as Direction;
+ const value = bodyDir || htmlDir;
+ this.value = (value === 'ltr' || value === 'rtl') ? value : 'ltr';
}
}
From bf9bc0da2e6f9a843429db97168cfe399e262ff1 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Wed, 1 Aug 2018 16:18:15 +0200
Subject: [PATCH 062/189] fix(live-announcer): duplicate live element when
coming in from the server (#12378)
Fixes the case where the user might get multiple live announcer elements, if they're coming in from a server-side-rendered page. Along the same lines as #11940.
---
.../live-announcer/live-announcer.spec.ts | 27 +++++++++++++++++++
src/cdk/a11y/live-announcer/live-announcer.ts | 15 ++++++++---
2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/src/cdk/a11y/live-announcer/live-announcer.spec.ts b/src/cdk/a11y/live-announcer/live-announcer.spec.ts
index 1d6285cc3ec5..7a37b21d4340 100644
--- a/src/cdk/a11y/live-announcer/live-announcer.spec.ts
+++ b/src/cdk/a11y/live-announcer/live-announcer.spec.ts
@@ -81,6 +81,33 @@ describe('LiveAnnouncer', () => {
tick(100);
expect(spy).toHaveBeenCalled();
}));
+
+ it('should ensure that there is only one live element at a time', fakeAsync(() => {
+ announcer.ngOnDestroy();
+ fixture.destroy();
+
+ TestBed.resetTestingModule().configureTestingModule({
+ imports: [A11yModule],
+ declarations: [TestApp],
+ });
+
+ const extraElement = document.createElement('div');
+ extraElement.classList.add('cdk-live-announcer-element');
+ document.body.appendChild(extraElement);
+
+ inject([LiveAnnouncer], (la: LiveAnnouncer) => {
+ announcer = la;
+ ariaLiveElement = getLiveElement();
+ fixture = TestBed.createComponent(TestApp);
+ })();
+
+ announcer.announce('Hey Google');
+ tick(100);
+
+ expect(document.body.querySelectorAll('.cdk-live-announcer-element').length)
+ .toBe(1, 'Expected only one live announcer element in the DOM.');
+ }));
+
});
describe('with a custom element', () => {
diff --git a/src/cdk/a11y/live-announcer/live-announcer.ts b/src/cdk/a11y/live-announcer/live-announcer.ts
index 84f7c6a7f6de..2891c45dc50d 100644
--- a/src/cdk/a11y/live-announcer/live-announcer.ts
+++ b/src/cdk/a11y/live-announcer/live-announcer.ts
@@ -30,14 +30,16 @@ export type AriaLivePoliteness = 'off' | 'polite' | 'assertive';
@Injectable({providedIn: 'root'})
export class LiveAnnouncer implements OnDestroy {
private readonly _liveElement: HTMLElement;
+ private _document: Document;
constructor(
@Optional() @Inject(LIVE_ANNOUNCER_ELEMENT_TOKEN) elementToken: any,
- @Inject(DOCUMENT) private _document: any) {
+ @Inject(DOCUMENT) _document: any) {
// We inject the live element and document as `any` because the constructor signature cannot
// reference browser globals (HTMLElement, Document) on non-browser environments, since having
// a class decorator causes TypeScript to preserve the constructor signature types.
+ this._document = _document;
this._liveElement = elementToken || this._createLiveElement();
}
@@ -73,9 +75,16 @@ export class LiveAnnouncer implements OnDestroy {
}
private _createLiveElement(): HTMLElement {
- let liveEl = this._document.createElement('div');
+ const elementClass = 'cdk-live-announcer-element';
+ const previousElements = this._document.getElementsByClassName(elementClass);
- liveEl.classList.add('cdk-live-announcer-element');
+ // Remove any old containers. This can happen when coming in from a server-side-rendered page.
+ for (let i = 0; i < previousElements.length; i++) {
+ previousElements[i].parentNode!.removeChild(previousElements[i]);
+ }
+
+ const liveEl = this._document.createElement('div');
+ liveEl.classList.add(elementClass);
liveEl.classList.add('cdk-visually-hidden');
liveEl.setAttribute('aria-atomic', 'true');
From 0c746c1bb68b23735141ccecfa7b93bff39c52a5 Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Wed, 1 Aug 2018 16:18:52 +0200
Subject: [PATCH 063/189] fix(checkbox): prevent error when disabling while
focused (#12327)
* Fixes that Angular throws an ExpressionChangedAfterItHasBeenCheckedError when disabling the checkbox while the component has been focused.
* Adds missing test for `NgModel` states after value change through view.
Related #12323
---
src/lib/checkbox/checkbox.spec.ts | 95 +++++++++++++++++--------------
src/lib/checkbox/checkbox.ts | 7 ++-
2 files changed, 58 insertions(+), 44 deletions(-)
diff --git a/src/lib/checkbox/checkbox.spec.ts b/src/lib/checkbox/checkbox.spec.ts
index b3bd3c63b0b5..1ae96a96d582 100644
--- a/src/lib/checkbox/checkbox.spec.ts
+++ b/src/lib/checkbox/checkbox.spec.ts
@@ -1,4 +1,11 @@
-import {ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing';
+import {
+ ComponentFixture,
+ fakeAsync,
+ TestBed,
+ tick,
+ flush,
+ flushMicrotasks,
+} from '@angular/core/testing';
import {FormControl, FormsModule, NgModel, ReactiveFormsModule} from '@angular/forms';
import {Component, DebugElement, ViewChild, Type} from '@angular/core';
import {By} from '@angular/platform-browser';
@@ -873,29 +880,63 @@ describe('MatCheckbox', () => {
let checkboxNativeElement: HTMLElement;
let checkboxInstance: MatCheckbox;
let inputElement: HTMLInputElement;
+ let ngModel: NgModel;
beforeEach(() => {
- fixture = createComponent(CheckboxWithFormDirectives);
+ fixture = createComponent(CheckboxWithNgModel);
+
+ fixture.componentInstance.isRequired = false;
fixture.detectChanges();
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox));
checkboxNativeElement = checkboxDebugElement.nativeElement;
checkboxInstance = checkboxDebugElement.componentInstance;
inputElement = checkboxNativeElement.querySelector('input');
+ ngModel = checkboxDebugElement.injector.get(NgModel);
});
- it('should be in pristine, untouched, and valid states initially', fakeAsync(() => {
- flush();
-
- let checkboxElement = fixture.debugElement.query(By.directive(MatCheckbox));
- let ngModel = checkboxElement.injector.get(NgModel);
-
+ it('should be pristine, untouched, and valid initially', () => {
expect(ngModel.valid).toBe(true);
expect(ngModel.pristine).toBe(true);
expect(ngModel.touched).toBe(false);
+ });
+
+ it('should have correct control states after interaction', fakeAsync(() => {
+ inputElement.click();
+ fixture.detectChanges();
+
+ // Flush the timeout that is being created whenever a `click` event has been fired by
+ // the underlying input.
+ flush();
+
+ // After the value change through interaction, the control should be dirty, but remain
+ // untouched as long as the focus is still on the underlying input.
+ expect(ngModel.pristine).toBe(false);
+ expect(ngModel.touched).toBe(false);
- // TODO(jelbourn): test that `touched` and `pristine` state are modified appropriately.
- // This is currently blocked on issues with async() and fakeAsync().
+ // If the input element loses focus, the control should remain dirty but should
+ // also turn touched.
+ dispatchFakeEvent(inputElement, 'blur');
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ expect(ngModel.pristine).toBe(false);
+ expect(ngModel.touched).toBe(true);
+ }));
+
+ it('should not throw an error when disabling while focused', fakeAsync(() => {
+ expect(() => {
+ // Focus the input element because after disabling, the `blur` event should automatically
+ // fire and not result in a changed after checked exception. Related: #12323
+ inputElement.focus();
+
+ // Flush the two nested timeouts from the FocusMonitor that are being created on `focus`.
+ flush();
+
+ checkboxInstance.disabled = true;
+ fixture.detectChanges();
+ flushMicrotasks();
+ }).not.toThrow();
}));
it('should toggle checked state on click', () => {
@@ -911,29 +952,9 @@ describe('MatCheckbox', () => {
expect(checkboxInstance.checked).toBe(false);
});
- });
-
- describe('with required ngModel', () => {
- let checkboxInstance: MatCheckbox;
- let inputElement: HTMLInputElement;
- let testComponent: CheckboxWithNgModel;
-
- beforeEach(() => {
- fixture = createComponent(CheckboxWithNgModel);
- fixture.detectChanges();
-
- let checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox));
- let checkboxNativeElement = checkboxDebugElement.nativeElement;
- testComponent = fixture.debugElement.componentInstance;
- checkboxInstance = checkboxDebugElement.componentInstance;
- inputElement = checkboxNativeElement.querySelector('input');
- });
it('should validate with RequiredTrue validator', () => {
- let checkboxElement = fixture.debugElement.query(By.directive(MatCheckbox));
- let ngModel = checkboxElement.injector.get(NgModel);
-
- testComponent.isRequired = true;
+ fixture.componentInstance.isRequired = true;
inputElement.click();
fixture.detectChanges();
@@ -1124,18 +1145,6 @@ class SingleCheckbox {
onCheckboxChange: (event?: MatCheckboxChange) => void = () => {};
}
-/** Simple component for testing an MatCheckbox with ngModel in a form. */
-@Component({
- template: `
-
- `,
-})
-class CheckboxWithFormDirectives {
- isGood: boolean = false;
-}
-
/** Simple component for testing an MatCheckbox with required ngModel. */
@Component({
template: `Be good`,
diff --git a/src/lib/checkbox/checkbox.ts b/src/lib/checkbox/checkbox.ts
index 1f206eda7a25..9203f7a2fca4 100644
--- a/src/lib/checkbox/checkbox.ts
+++ b/src/lib/checkbox/checkbox.ts
@@ -341,7 +341,12 @@ export class MatCheckbox extends _MatCheckboxMixinBase implements ControlValueAc
this._focusRipple = null;
}
- this._onTouched();
+ // When a focused element becomes disabled, the browser *immediately* fires a blur event.
+ // Angular does not expect events to be raised during change detection, so any state change
+ // (such as a form control's 'ng-touched') will cause a changed-after-checked error.
+ // See https://github.com/angular/angular/issues/17793. To work around this, we defer telling
+ // the form control it has been touched until the next tick.
+ Promise.resolve().then(() => this._onTouched());
}
}
From 80f6929acc71838dd13601ba98d7aeb0ed17a288 Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Wed, 1 Aug 2018 16:19:29 +0200
Subject: [PATCH 064/189] fix(slide-toggle): prevent error when disabling while
focused (#12325)
Fixes Angular throwing an `ExpressionChangedAfterItHasBeenCheckedError` when disabling the slide-toggle while the component has been focused.
Fixes #12323
---
src/lib/slide-toggle/slide-toggle.spec.ts | 36 +++++++++++++++++++----
src/lib/slide-toggle/slide-toggle.ts | 7 ++++-
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/src/lib/slide-toggle/slide-toggle.spec.ts b/src/lib/slide-toggle/slide-toggle.spec.ts
index f9e512118463..84eaee5e0d72 100644
--- a/src/lib/slide-toggle/slide-toggle.spec.ts
+++ b/src/lib/slide-toggle/slide-toggle.spec.ts
@@ -1,7 +1,14 @@
import {MutationObserverFactory} from '@angular/cdk/observers';
import {dispatchFakeEvent} from '@angular/cdk/testing';
import {Component} from '@angular/core';
-import {ComponentFixture, fakeAsync, flushMicrotasks, TestBed, tick} from '@angular/core/testing';
+import {
+ ComponentFixture,
+ fakeAsync,
+ flush,
+ flushMicrotasks,
+ TestBed,
+ tick,
+} from '@angular/core/testing';
import {FormControl, FormsModule, NgModel, ReactiveFormsModule} from '@angular/forms';
import {defaultRippleAnimationConfig} from '@angular/material/core';
import {By, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
@@ -773,7 +780,7 @@ describe('MatSlideToggle with forms', () => {
expect(slideToggleElement.classList).toContain('mat-checked');
}));
- it('should have the correct control state initially and after interaction', () => {
+ it('should have the correct control state initially and after interaction', fakeAsync(() => {
// The control should start off valid, pristine, and untouched.
expect(slideToggleModel.valid).toBe(true);
expect(slideToggleModel.pristine).toBe(true);
@@ -795,13 +802,31 @@ describe('MatSlideToggle with forms', () => {
// also turn touched.
dispatchFakeEvent(inputElement, 'blur');
fixture.detectChanges();
+ flushMicrotasks();
expect(slideToggleModel.valid).toBe(true);
expect(slideToggleModel.pristine).toBe(false);
expect(slideToggleModel.touched).toBe(true);
- });
+ }));
+
+ it('should not throw an error when disabling while focused', fakeAsync(() => {
+ expect(() => {
+ // Focus the input element because after disabling, the `blur` event should automatically
+ // fire and not result in a changed after checked exception. Related: #12323
+ inputElement.focus();
+
+ // Flush the two nested timeouts from the FocusMonitor that are being created on `focus`.
+ flush();
+
+ slideToggle.disabled = true;
+ fixture.detectChanges();
+ flushMicrotasks();
+ }).not.toThrow();
+ }));
+
+ it('should not set the control to touched when changing the state programmatically',
+ fakeAsync(() => {
- it('should not set the control to touched when changing the state programmatically', () => {
// The control should start off with being untouched.
expect(slideToggleModel.touched).toBe(false);
@@ -815,10 +840,11 @@ describe('MatSlideToggle with forms', () => {
// also turn touched.
dispatchFakeEvent(inputElement, 'blur');
fixture.detectChanges();
+ flushMicrotasks();
expect(slideToggleModel.touched).toBe(true);
expect(slideToggleElement.classList).toContain('mat-checked');
- });
+ }));
it('should not set the control to touched when changing the model', fakeAsync(() => {
// The control should start off with being untouched.
diff --git a/src/lib/slide-toggle/slide-toggle.ts b/src/lib/slide-toggle/slide-toggle.ts
index ea42698e5328..1306a1bd5519 100644
--- a/src/lib/slide-toggle/slide-toggle.ts
+++ b/src/lib/slide-toggle/slide-toggle.ts
@@ -289,7 +289,12 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro
// For keyboard focus show a persistent ripple as focus indicator.
this._focusRipple = this._ripple.launch(0, 0, {persistent: true});
} else if (!focusOrigin) {
- this.onTouched();
+ // When a focused element becomes disabled, the browser *immediately* fires a blur event.
+ // Angular does not expect events to be raised during change detection, so any state change
+ // (such as a form control's 'ng-touched') will cause a changed-after-checked error.
+ // See https://github.com/angular/angular/issues/17793. To work around this, we defer telling
+ // the form control it has been touched until the next tick.
+ Promise.resolve().then(() => this.onTouched());
// Fade out and clear the focus ripple if one is currently present.
if (this._focusRipple) {
From 39d40f3a1cb7f5ea28f2803ae299107e66bbf370 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Fri, 3 Aug 2018 16:04:18 +0200
Subject: [PATCH 065/189] fix(table): error if row definition is on an
ng-container (#12462)
Fixes the table throwing an error if the row definitions are on an `ng-container`.
Fixes #12460.
---
src/cdk/table/sticky-styler.ts | 7 ++++++
src/lib/table/table.spec.ts | 41 +++++++++++++++++++++++++++++++++-
2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/src/cdk/table/sticky-styler.ts b/src/cdk/table/sticky-styler.ts
index 8525fdb3e8b9..10edad73e593 100644
--- a/src/cdk/table/sticky-styler.ts
+++ b/src/cdk/table/sticky-styler.ts
@@ -45,7 +45,14 @@ export class StickyStyler {
*/
clearStickyPositioning(rows: HTMLElement[], stickyDirections: StickyDirection[]) {
for (const row of rows) {
+ // If the row isn't an element (e.g. if it's an `ng-container`),
+ // it won't have inline styles or `children` so we skip it.
+ if (row.nodeType !== row.ELEMENT_NODE) {
+ continue;
+ }
+
this._removeStickyStyle(row, stickyDirections);
+
for (let i = 0; i < row.children.length; i++) {
const cell = row.children[i] as HTMLElement;
this._removeStickyStyle(cell, stickyDirections);
diff --git a/src/lib/table/table.spec.ts b/src/lib/table/table.spec.ts
index b43348c33111..d8a8c8b0c086 100644
--- a/src/lib/table/table.spec.ts
+++ b/src/lib/table/table.spec.ts
@@ -1,6 +1,13 @@
import {DataSource} from '@angular/cdk/collections';
import {Component, OnInit, ViewChild} from '@angular/core';
-import {async, ComponentFixture, fakeAsync, flushMicrotasks, TestBed} from '@angular/core/testing';
+import {
+ async,
+ ComponentFixture,
+ fakeAsync,
+ flushMicrotasks,
+ TestBed,
+ tick,
+} from '@angular/core/testing';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {BehaviorSubject, Observable} from 'rxjs';
import {MatPaginator, MatPaginatorModule} from '../paginator/index';
@@ -22,6 +29,7 @@ describe('MatTable', () => {
MatTableWithSortApp,
MatTableWithPaginatorApp,
StickyTableApp,
+ TableWithNgContainerRow,
],
}).compileComponents();
}));
@@ -127,6 +135,16 @@ describe('MatTable', () => {
expect(stuckCellElement.classList).toContain('mat-table-sticky');
});
+ // Note: needs to be fakeAsync so it catches the error.
+ it('should not throw when a row definition is on an ng-container', fakeAsync(() => {
+ const fixture = TestBed.createComponent(TableWithNgContainerRow);
+
+ expect(() => {
+ fixture.detectChanges();
+ tick();
+ }).not.toThrow();
+ }));
+
describe('with MatTableDataSource and sort/pagination/filter', () => {
let tableElement: HTMLElement;
let fixture: ComponentFixture;
@@ -750,6 +768,27 @@ class MatTableWithPaginatorApp implements OnInit {
}
}
+@Component({
+ template: `
+
+
+ Column A
+ {{row.a}}
+
+
+
+
+
+
+
+ `
+})
+class TableWithNgContainerRow {
+ dataSource: FakeDataSource | null = new FakeDataSource();
+ columnsToRender = ['column_a'];
+}
+
+
function getElements(element: Element, query: string): Element[] {
return [].slice.call(element.querySelectorAll(query));
}
From 747231a88684005eedaa7a6785b2ff35d1f61408 Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Fri, 3 Aug 2018 16:08:49 +0200
Subject: [PATCH 066/189] fix(menu): menu content data being cleared when
lazy-loaded content is reused between nested triggers (#12476)
Fixes an issue where a nested menu with lazy-loaded that is reused between multiple triggers will clear its content once an alternate trigger is hovered. The issue comes from the fact that we wait for the exit animation to finish before we detach the content, which ends up detaching the content of the new trigger as well.
Fixes #12467.
---
src/lib/menu/menu-content.ts | 5 +++++
src/lib/menu/menu-trigger.ts | 11 ++++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/src/lib/menu/menu-content.ts b/src/lib/menu/menu-content.ts
index e8d16b824ea5..2329777becb5 100644
--- a/src/lib/menu/menu-content.ts
+++ b/src/lib/menu/menu-content.ts
@@ -18,6 +18,7 @@ import {
} from '@angular/core';
import {TemplatePortal, DomPortalOutlet} from '@angular/cdk/portal';
import {DOCUMENT} from '@angular/common';
+import {Subject} from 'rxjs';
/**
* Menu content that will be rendered lazily once the menu is opened.
@@ -29,6 +30,9 @@ export class MatMenuContent implements OnDestroy {
private _portal: TemplatePortal;
private _outlet: DomPortalOutlet;
+ /** Emits when the menu content has been attached. */
+ _attached = new Subject();
+
constructor(
private _template: TemplateRef,
private _componentFactoryResolver: ComponentFactoryResolver,
@@ -60,6 +64,7 @@ export class MatMenuContent implements OnDestroy {
// risk it staying attached to a pane that's no longer in the DOM.
element.parentNode!.insertBefore(this._outlet.outletElement, element);
this._portal.attach(this._outlet, context);
+ this._attached.next();
}
/**
diff --git a/src/lib/menu/menu-trigger.ts b/src/lib/menu/menu-trigger.ts
index 329f16abb189..8e00ee787e18 100644
--- a/src/lib/menu/menu-trigger.ts
+++ b/src/lib/menu/menu-trigger.ts
@@ -245,9 +245,14 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
if (menu.lazyContent) {
// Wait for the exit animation to finish before detaching the content.
menu._animationDone
- .pipe(filter(event => event.toState === 'void'), take(1))
- .subscribe(() => {
- menu.lazyContent!.detach();
+ .pipe(
+ filter(event => event.toState === 'void'),
+ take(1),
+ // Interrupt if the content got re-attached.
+ takeUntil(menu.lazyContent._attached)
+ )
+ .subscribe(() => menu.lazyContent!.detach(), undefined, () => {
+ // No matter whether the content got re-attached, reset the menu.
this._resetMenu();
});
} else {
From e0a3b47563a2c700af25210067aef67c61283eba Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Fri, 3 Aug 2018 01:44:00 +0200
Subject: [PATCH 067/189] chore(select): fix flaky positioning test (#12496)
Fixes a flaky test that is failing on iOS.
---
src/lib/select/select.spec.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/lib/select/select.spec.ts b/src/lib/select/select.spec.ts
index fe29c1e208e5..613f41aa2559 100644
--- a/src/lib/select/select.spec.ts
+++ b/src/lib/select/select.spec.ts
@@ -3318,7 +3318,8 @@ describe('MatSelect', () => {
let panelLeft = document.querySelector('.mat-select-panel')!.getBoundingClientRect().left;
- expect(panelLeft).toBeGreaterThan(0, `Expected select panel to be inside the viewport.`);
+ expect(panelLeft)
+ .toBeGreaterThanOrEqual(0, `Expected select panel to be inside the viewport.`);
fixture.componentInstance.select.close();
fixture.detectChanges();
@@ -3330,7 +3331,7 @@ describe('MatSelect', () => {
panelLeft = document.querySelector('.mat-select-panel')!.getBoundingClientRect().left;
- expect(panelLeft).toBeGreaterThan(0,
+ expect(panelLeft).toBeGreaterThanOrEqual(0,
`Expected select panel continue being inside the viewport.`);
}));
});
From 6c9190260782afebfa9187c3958a37e64b906057 Mon Sep 17 00:00:00 2001
From: Jeremy Elbourn
Date: Tue, 7 Aug 2018 11:34:14 -0700
Subject: [PATCH 068/189] chore: bump version to 6.4.3 w/ changelog (#12558)
---
CHANGELOG.md | 25 +++++++++++++++++++++++++
package-lock.json | 8 ++++----
package.json | 2 +-
3 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a04bcfcc699..83fbee31180e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,28 @@
+
+## [6.4.3 monelite-meeple](https://github.com/angular/material2/compare/6.4.2...6.4.3) (2018-08-07)
+
+
+### Bug Fixes
+
+* **bidi:** default invalid directionality values to ltr ([#12396](https://github.com/angular/material2/issues/12396)) ([58361f1](https://github.com/angular/material2/commit/58361f1))
+* **checkbox:** prevent error when disabling while focused ([#12327](https://github.com/angular/material2/issues/12327)) ([0c746c1](https://github.com/angular/material2/commit/0c746c1)), closes [#12323](https://github.com/angular/material2/issues/12323)
+* **chips:** dynamic chip input placeholder changes not being propagated to form field ([#12422](https://github.com/angular/material2/issues/12422)) ([5053532](https://github.com/angular/material2/commit/5053532)), closes [#11861](https://github.com/angular/material2/issues/11861)
+* **chips:** focus indication not visible in high contrast mode ([#12431](https://github.com/angular/material2/issues/12431)) ([3652707](https://github.com/angular/material2/commit/3652707))
+* **drag-drop:** account for transition-delay when waiting for the animation to finish ([#12466](https://github.com/angular/material2/issues/12466)) ([3580fb5](https://github.com/angular/material2/commit/3580fb5))
+* **form-field:** reset inputs not being reset on safari ([#12413](https://github.com/angular/material2/issues/12413)) ([952b553](https://github.com/angular/material2/commit/952b553)), closes [#12408](https://github.com/angular/material2/issues/12408)
+* **form-field:** unable to distinguish disabled form field in high contrast mode ([#12445](https://github.com/angular/material2/issues/12445)) ([212bd0b](https://github.com/angular/material2/commit/212bd0b))
+* **live-announcer:** duplicate live element when coming in from the server ([#12378](https://github.com/angular/material2/issues/12378)) ([bf9bc0d](https://github.com/angular/material2/commit/bf9bc0d)), closes [#11940](https://github.com/angular/material2/issues/11940)
+* **menu:** menu content data being cleared when lazy-loaded content is reused between nested triggers ([#12476](https://github.com/angular/material2/issues/12476)) ([747231a](https://github.com/angular/material2/commit/747231a)), closes [#12467](https://github.com/angular/material2/issues/12467)
+* **slide-toggle:** prevent error when disabling while focused ([#12325](https://github.com/angular/material2/issues/12325)) ([80f6929](https://github.com/angular/material2/commit/80f6929)), closes [#12323](https://github.com/angular/material2/issues/12323)
+* **table:** error if row definition is on an ng-container ([#12462](https://github.com/angular/material2/issues/12462)) ([39d40f3](https://github.com/angular/material2/commit/39d40f3)), closes [#12460](https://github.com/angular/material2/issues/12460)
+
+
+### Performance Improvements
+
+* **overlay:** remove detached overlays from the DOM ([#12414](https://github.com/angular/material2/issues/12414)) ([40d8ae4](https://github.com/angular/material2/commit/40d8ae4)), closes [#12341](https://github.com/angular/material2/issues/12341)
+
+
+
## [6.4.2 chalk-window](https://github.com/angular/material2/compare/6.4.1...6.4.2) (2018-07-30)
diff --git a/package-lock.json b/package-lock.json
index 85c073011a09..297a2d1d7e87 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "material2-srcs",
- "version": "6.3.3",
+ "version": "6.4.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -3427,7 +3427,7 @@
"split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
- "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
+ "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=",
"dev": true,
"requires": {
"through": "2"
@@ -4891,7 +4891,7 @@
},
"event-stream": {
"version": "3.3.4",
- "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+ "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
"integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
"dev": true,
"requires": {
@@ -13464,7 +13464,7 @@
},
"onetime": {
"version": "1.1.0",
- "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
},
diff --git a/package.json b/package.json
index 2e9575fe59ea..4c23731861ac 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"docs": "gulp docs",
"api": "gulp api-docs"
},
- "version": "6.4.2",
+ "version": "6.4.3",
"license": "MIT",
"engines": {
"node": ">= 5.4.1"
From 2798084ce8f6b6355f92d1667d8637be8008438e Mon Sep 17 00:00:00 2001
From: Paul Gschwendtner
Date: Tue, 7 Aug 2018 22:31:59 +0200
Subject: [PATCH 069/189] fix(tabs): animation running after initialization
(#12549)
---
src/lib/tabs/tab-body.spec.ts | 32 +++++++++++++++++++++++---------
src/lib/tabs/tab-body.ts | 2 +-
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/src/lib/tabs/tab-body.spec.ts b/src/lib/tabs/tab-body.spec.ts
index 8c726a25388c..0eb026ffd4c2 100644
--- a/src/lib/tabs/tab-body.spec.ts
+++ b/src/lib/tabs/tab-body.spec.ts
@@ -33,19 +33,33 @@ describe('MatTabBody', () => {
describe('when initialized as center', () => {
let fixture: ComponentFixture;
+ it('should be center position if origin is unchanged', () => {
+ fixture = TestBed.createComponent(SimpleTabBodyApp);
+ fixture.componentInstance.position = 0;
+ fixture.detectChanges();
+
+ expect(fixture.componentInstance.tabBody._position).toBe('center');
+ });
+
+ it('should be center position if origin is explicitly set to null', () => {
+ fixture = TestBed.createComponent(SimpleTabBodyApp);
+ fixture.componentInstance.position = 0;
+
+ // It can happen that the `origin` is explicitly set to null through the Angular input
+ // binding. This test should ensure that the body does properly such origin value.
+ // The `MatTab` class sets the origin by default to null. See related issue: #12455
+ fixture.componentInstance.origin = null;
+ fixture.detectChanges();
+
+ expect(fixture.componentInstance.tabBody._position).toBe('center');
+ });
+
describe('in LTR direction', () => {
+
beforeEach(() => {
dir = 'ltr';
fixture = TestBed.createComponent(SimpleTabBodyApp);
});
-
- it('should be center position without origin', () => {
- fixture.componentInstance.position = 0;
- fixture.detectChanges();
-
- expect(fixture.componentInstance.tabBody._position).toBe('center');
- });
-
it('should be left-origin-center position with negative or zero origin', () => {
fixture.componentInstance.position = 0;
fixture.componentInstance.origin = 0;
@@ -176,7 +190,7 @@ describe('MatTabBody', () => {
class SimpleTabBodyApp implements AfterContentInit {
content: TemplatePortal;
position: number;
- origin: number;
+ origin: number | null;
@ViewChild(MatTabBody) tabBody: MatTabBody;
@ViewChild(TemplateRef) template: TemplateRef;
diff --git a/src/lib/tabs/tab-body.ts b/src/lib/tabs/tab-body.ts
index 8654b3ddffa6..d1f26c3bf4fb 100644
--- a/src/lib/tabs/tab-body.ts
+++ b/src/lib/tabs/tab-body.ts
@@ -173,7 +173,7 @@ export class MatTabBody implements OnInit, OnDestroy {
* special position states that transition the tab from the left or right before centering.
*/
ngOnInit() {
- if (this._position == 'center' && this.origin !== undefined) {
+ if (this._position == 'center' && this.origin != null) {
this._position = this._computePositionFromOrigin();
}
}
From 5b0eed3f568bf0174285fd25501fd1386de2b80e Mon Sep 17 00:00:00 2001
From: Joey Perrott
Date: Tue, 7 Aug 2018 13:33:43 -0700
Subject: [PATCH 070/189] fix(tree): include constructors on MatTree classes to
allow es6 builds (#12556)
---
src/lib/tree/node.ts | 12 +++++++++++-
src/lib/tree/padding.ts | 18 ++++++++++++++++--
src/lib/tree/toggle.ts | 11 ++++++++++-
src/lib/tree/tree.ts | 18 +++++++++++++++++-
4 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/src/lib/tree/node.ts b/src/lib/tree/node.ts
index 8a3aa6b3c03d..fc81db4efee7 100644
--- a/src/lib/tree/node.ts
+++ b/src/lib/tree/node.ts
@@ -21,7 +21,8 @@ import {
Input,
IterableDiffers,
OnDestroy,
- QueryList
+ QueryList,
+ TemplateRef,
} from '@angular/core';
import {CanDisable, HasTabIndex, mixinDisabled, mixinTabIndex} from '@angular/material/core';
import {MatTreeNodeOutlet} from './outlet';
@@ -70,6 +71,15 @@ export class MatTreeNode extends _MatTreeNodeMixinBase
})
export class MatTreeNodeDef extends CdkTreeNodeDef {
@Input('matTreeNode') data: T;
+
+ // TODO(andrewseguin): Remove this explicitly set constructor when the compiler knows how to
+ // properly build the es6 version of the class. Currently sets ctorParameters to empty due to a
+ // fixed bug.
+ // https://github.com/angular/tsickle/pull/760 - tsickle PR that fixed this
+ // https://github.com/angular/angular/pull/23531 - updates compiler-cli to fixed version
+ constructor(template: TemplateRef) {
+ super(template);
+ }
}
/**
diff --git a/src/lib/tree/padding.ts b/src/lib/tree/padding.ts
index 5738c82b4ee3..f3627fb1cf0e 100644
--- a/src/lib/tree/padding.ts
+++ b/src/lib/tree/padding.ts
@@ -5,8 +5,9 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
-import {CdkTreeNodePadding} from '@angular/cdk/tree';
-import {Directive, Input} from '@angular/core';
+import {CdkTreeNodePadding, CdkTreeNode, CdkTree} from '@angular/cdk/tree';
+import {Directionality} from '@angular/cdk/bidi';
+import {Directive, Input, Optional, Renderer2, ElementRef} from '@angular/core';
/**
@@ -23,4 +24,17 @@ export class MatTreeNodePadding extends CdkTreeNodePadding {
/** The indent for each level. Default number 40px from material design menu sub-menu spec. */
@Input('matTreeNodePaddingIndent') indent: number;
+
+ // TODO(andrewseguin): Remove this explicitly set constructor when the compiler knows how to
+ // properly build the es6 version of the class. Currently sets ctorParameters to empty due to a
+ // fixed bug.
+ // https://github.com/angular/tsickle/pull/760 - tsickle PR that fixed this
+ // https://github.com/angular/angular/pull/23531 - updates compiler-cli to fixed version
+ constructor(_treeNode: CdkTreeNode,
+ _tree: CdkTree,
+ _renderer: Renderer2,
+ _element: ElementRef,
+ @Optional() _dir: Directionality) {
+ super(_treeNode, _tree, _renderer, _element, _dir);
+ }
}
diff --git a/src/lib/tree/toggle.ts b/src/lib/tree/toggle.ts
index 19542d8a03b4..1ce62485d146 100644
--- a/src/lib/tree/toggle.ts
+++ b/src/lib/tree/toggle.ts
@@ -7,7 +7,7 @@
*/
import {Directive, Input} from '@angular/core';
-import {CdkTreeNodeToggle} from '@angular/cdk/tree';
+import {CdkTreeNodeToggle, CdkTree, CdkTreeNode} from '@angular/cdk/tree';
/**
* Wrapper for the CdkTree's toggle with Material design styles.
@@ -21,4 +21,13 @@ import {CdkTreeNodeToggle} from '@angular/cdk/tree';
})
export class MatTreeNodeToggle extends CdkTreeNodeToggle {
@Input('matTreeNodeToggleRecursive') recursive: boolean = false;
+
+ // TODO(andrewseguin): Remove this explicitly set constructor when the compiler knows how to
+ // properly build the es6 version of the class. Currently sets ctorParameters to empty due to a
+ // fixed bug.
+ // https://github.com/angular/tsickle/pull/760 - tsickle PR that fixed this
+ // https://github.com/angular/angular/pull/23531 - updates compiler-cli to fixed version
+ constructor(_tree: CdkTree, _treeNode: CdkTreeNode) {
+ super(_tree, _treeNode);
+ }
}
diff --git a/src/lib/tree/tree.ts b/src/lib/tree/tree.ts
index e2ebe5849918..f8f5181975c0 100644
--- a/src/lib/tree/tree.ts
+++ b/src/lib/tree/tree.ts
@@ -6,7 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation} from '@angular/core';
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ViewChild,
+ ViewEncapsulation,
+ IterableDiffers,
+} from '@angular/core';
import {CdkTree} from '@angular/cdk/tree';
import {MatTreeNodeOutlet} from './outlet';
@@ -30,5 +37,14 @@ import {MatTreeNodeOutlet} from './outlet';
export class MatTree extends CdkTree {
// Outlets within the tree's template where the dataNodes will be inserted.
@ViewChild(MatTreeNodeOutlet) _nodeOutlet: MatTreeNodeOutlet;
+
+ // TODO(andrewseguin): Remove this explicitly set constructor when the compiler knows how to
+ // properly build the es6 version of the class. Currently sets ctorParameters to empty due to a
+ // fixed bug.
+ // https://github.com/angular/tsickle/pull/760 - tsickle PR that fixed this
+ // https://github.com/angular/angular/pull/23531 - updates compiler-cli to fixed version
+ constructor(_differs: IterableDiffers, _changeDetectorRef: ChangeDetectorRef) {
+ super(_differs, _changeDetectorRef);
+ }
}
From dcae875e9da8f5d179c3533f646ffb6366e3683a Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Tue, 7 Aug 2018 22:34:43 +0200
Subject: [PATCH 071/189] fix(button-toggle): forward tabindex to underlying
button (#12538)
---
src/lib/button-toggle/button-toggle.html | 1 +
src/lib/button-toggle/button-toggle.spec.ts | 28 +++++++++++++++++++++
src/lib/button-toggle/button-toggle.ts | 12 ++++++++-
3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/src/lib/button-toggle/button-toggle.html b/src/lib/button-toggle/button-toggle.html
index b0ddfb90e4c2..400550c5bbdc 100644
--- a/src/lib/button-toggle/button-toggle.html
+++ b/src/lib/button-toggle/button-toggle.html
@@ -1,6 +1,7 @@