From ca00dfb9589ea220f4ec561db48fcf279eeabe71 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 25 Jun 2025 18:18:15 +0200 Subject: [PATCH 1/9] build: links to headers not working (#31436) Fixes that a previous commit stopped setting the `example` on the `HeaderLink` which means that its link isn't constructed correctly. (cherry picked from commit ea7148ca89841f54726895b98f425c25fa167180) --- docs/src/app/shared/doc-viewer/doc-viewer.ts | 18 ++++++++++------- docs/src/app/shared/doc-viewer/header-link.ts | 20 +++++++------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/docs/src/app/shared/doc-viewer/doc-viewer.ts b/docs/src/app/shared/doc-viewer/doc-viewer.ts index 89b3b73cc81b..ed1b7b05f682 100644 --- a/docs/src/app/shared/doc-viewer/doc-viewer.ts +++ b/docs/src/app/shared/doc-viewer/doc-viewer.ts @@ -187,13 +187,17 @@ export class DocViewer implements OnDestroy { const examplePortal = new ComponentPortal(componentClass, this._viewContainerRef); const exampleViewer = portalHost.attach(examplePortal); const exampleViewerComponent = exampleViewer.instance; - if (example !== null && componentClass === ExampleViewer) { - DocViewer._initExampleViewer( - exampleViewerComponent as ExampleViewer, - example, - file, - region, - ); + if (example !== null) { + if (componentClass === ExampleViewer) { + DocViewer._initExampleViewer( + exampleViewerComponent as ExampleViewer, + example, + file, + region, + ); + } else { + (exampleViewerComponent as HeaderLink).example.set(example); + } } this._portalHosts.push(portalHost); }); diff --git a/docs/src/app/shared/doc-viewer/header-link.ts b/docs/src/app/shared/doc-viewer/header-link.ts index a518be234af6..889e078095a8 100644 --- a/docs/src/app/shared/doc-viewer/header-link.ts +++ b/docs/src/app/shared/doc-viewer/header-link.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {Component, inject} from '@angular/core'; +import {Component, computed, inject, signal} from '@angular/core'; import {Router} from '@angular/router'; import {MatIcon} from '@angular/material/icon'; @@ -18,7 +18,7 @@ import {MatIcon} from '@angular/material/icon'; selector: 'header-link', template: ` + [attr.aria-describedby]="example()" [href]="_fragmentUrl()"> link `, @@ -29,18 +29,12 @@ export class HeaderLink { * Id of the anchor element. Note that is uses "example" because we instantiate the * header link components through the ComponentPortal. */ - example: string = ''; + readonly example = signal(''); /** Base URL that is used to build an absolute fragment URL. */ - private _baseUrl: string; + private _baseUrl = inject(Router).url.split('#')[0]; - constructor() { - const router = inject(Router); - - this._baseUrl = router.url.split('#')[0]; - } - - _getFragmentUrl(): string { - return `${this._baseUrl}#${this.example}`; - } + protected readonly _fragmentUrl = computed(() => { + return `${this._baseUrl}#${this.example()}`; + }); } From bdfeb04c3a220121d7b98b9ac8147e0cfdcdfeb6 Mon Sep 17 00:00:00 2001 From: Terence Honles Date: Thu, 26 Jun 2025 00:34:24 -0700 Subject: [PATCH 2/9] fix(google-maps): fix update schematic (#31448) This change fixes the `updateToV20` schematic which should be a factory function not the schematic itself. (cherry picked from commit 4052130ee0dc627242a7f863f84eced4a0af048f) --- src/google-maps/schematics/ng-update/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/google-maps/schematics/ng-update/index.ts b/src/google-maps/schematics/ng-update/index.ts index e195902f23b5..ca337a1bd02b 100644 --- a/src/google-maps/schematics/ng-update/index.ts +++ b/src/google-maps/schematics/ng-update/index.ts @@ -6,5 +6,9 @@ * found in the LICENSE file at https://angular.dev/license */ +import {Rule} from '@angular-devkit/schematics'; + /** Entry point for the migration schematics with target of Angular Material v20 */ -export function updateToV20(): void {} +export function updateToV20(): Rule { + return () => {}; +} From ed5a1e0ca3d97fa7719aa657f569ac1cdfe7c552 Mon Sep 17 00:00:00 2001 From: Pascal Weyrich Date: Thu, 26 Jun 2025 10:59:52 +0200 Subject: [PATCH 3/9] docs: correct treeNodeDef selectors (#31421) (cherry picked from commit b5fbf52fff33101a16595d274c425a377dfc9228) --- src/cdk/tree/tree.md | 18 +++++++++--------- src/material/tree/tree.md | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cdk/tree/tree.md b/src/cdk/tree/tree.md index 30de3315ce20..9f8e0c7163f8 100644 --- a/src/cdk/tree/tree.md +++ b/src/cdk/tree/tree.md @@ -55,11 +55,11 @@ In order to use the tree, you must define a tree node template. There are two ty template defines the look of the tree node, expansion/collapsing control and the structure for nested children nodes. -A node definition is specified via any element with `cdkNodeDef`. This directive exports the node +A node definition is specified via any element with `cdkTreeNodeDef`. This directive exports the node data to be used in any bindings in the node template. ```html - + {{node.key}}: {{node.value}} ``` @@ -80,7 +80,7 @@ When using nested tree nodes, the node template must contain a `cdkTreeNodeOutle where the children of the node will be rendered. ```html - + {{node.value}} @@ -96,7 +96,7 @@ a tree node recursively by setting `[cdkTreeNodeToggleRecursive]` to true. activation. For icon buttons, ensure that `aria-label` is provided. ```html - + @@ -110,7 +110,7 @@ The `cdkTreeNodePadding` directive can be placed in a flat tree's node template information of a flat tree node. ```html - + {{node.value}} ``` @@ -125,10 +125,10 @@ The tree may include multiple node templates, where a template is chosen for a particular data node via the `when` predicate of the template. ```html - + {{node.value}} - + [ A special node {{node.value}} ] ``` @@ -200,11 +200,11 @@ interaction. ```html ``` In this example, `$event` contains the node's data and is equivalent to the implicit data passed in -the `cdkNodeDef` context. +the `cdkTreeNodeDef` context. diff --git a/src/material/tree/tree.md b/src/material/tree/tree.md index a9eba1238d0c..e2411fa4cda0 100644 --- a/src/material/tree/tree.md +++ b/src/material/tree/tree.md @@ -55,11 +55,11 @@ In order to use the tree, you must define a tree node template. There are two ty template defines the look of the tree node, expansion/collapsing control and the structure for nested children nodes. -A node definition is specified via any element with `matNodeDef`. This directive exports the node +A node definition is specified via any element with `matTreeNodeDef`. This directive exports the node data to be used in any bindings in the node template. ```html - + {{node.key}}: {{node.value}} ``` @@ -80,7 +80,7 @@ When using nested tree nodes, the node template must contain a `matTreeNodeOutle where the children of the node will be rendered. ```html - + {{node.value}} @@ -96,7 +96,7 @@ a tree node recursively by setting `[matTreeNodeToggleRecursive]` to true. activation. For icon buttons, ensure that `aria-label` is provided. ```html - + @@ -119,7 +119,7 @@ The `matTreeNodePadding` can be placed in a flat tree's node template to display information of a flat tree node. ```html - + {{node.value}} ``` @@ -134,10 +134,10 @@ The tree may include multiple node templates, where a template is chosen for a particular data node via the `when` predicate of the template. ```html - + {{node.value}} - + [ A special node {{node.value}} ] ``` @@ -209,11 +209,11 @@ interaction. ```html ``` In this example, `$event` contains the node's data and is equivalent to the implicit data passed in -the `matNodeDef` context. +the `matTreeNodeDef` context. From a6f449958345aad5bb4fae59906e1bab004277f9 Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Fri, 27 Jun 2025 09:12:25 -0600 Subject: [PATCH 4/9] build: update github/codeql-action action to v3.29.1 (#31458) See associated pull request for more information. (cherry picked from commit 464adf010ca94f504e2f5c920c1cc2b5c6495826) --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 6e37f2cc52b5..4a7f801b2bea 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -47,6 +47,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 + uses: github/codeql-action/upload-sarif@39edc492dbe16b1465b0cafca41432d857bdb31a # v3.29.1 with: sarif_file: results.sarif From a5d5ed89f5bdc98351b7819ee31a500d55346d1d Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 1 Jul 2025 07:15:48 +0200 Subject: [PATCH 5/9] refactor(multiple): clean up usages of DOCUMENT (#31461) We had several places that were optionally injecting `DOCUMENT`, because historically it wasn't guaranteed to be there. That shouldn't be the case anymore so we can clean them up. (cherry picked from commit a6a385c887c994563af5ae7600c928ae0cae6718) --- goldens/cdk/a11y/index.api.md | 2 +- goldens/cdk/text-field/index.api.md | 2 +- src/cdk/a11y/focus-monitor/focus-monitor.ts | 14 ++++---------- src/cdk/dialog/dialog-container.ts | 2 +- src/cdk/scrolling/viewport-ruler.ts | 2 +- src/cdk/text-field/autosize.ts | 2 +- src/material/sidenav/drawer.ts | 6 ++---- 7 files changed, 11 insertions(+), 19 deletions(-) diff --git a/goldens/cdk/a11y/index.api.md b/goldens/cdk/a11y/index.api.md index ecd9b7654403..916d9c30d76c 100644 --- a/goldens/cdk/a11y/index.api.md +++ b/goldens/cdk/a11y/index.api.md @@ -175,7 +175,7 @@ export class FocusKeyManager extends ListKeyManager { // @public export class FocusMonitor implements OnDestroy { constructor(...args: unknown[]); - protected _document?: Document | null | undefined; + protected _document: Document; focusVia(element: HTMLElement, origin: FocusOrigin, options?: FocusOptions_2): void; focusVia(element: ElementRef, origin: FocusOrigin, options?: FocusOptions_2): void; monitor(element: HTMLElement, checkChildren?: boolean): Observable; diff --git a/goldens/cdk/text-field/index.api.md b/goldens/cdk/text-field/index.api.md index cb1f19df72e8..b9ab33d29cf3 100644 --- a/goldens/cdk/text-field/index.api.md +++ b/goldens/cdk/text-field/index.api.md @@ -51,7 +51,7 @@ export class CdkAutofill implements OnDestroy, OnInit { // @public export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy { constructor(...args: unknown[]); - protected _document?: Document | null | undefined; + protected _document: Document; get enabled(): boolean; set enabled(value: boolean); get maxRows(): number; diff --git a/src/cdk/a11y/focus-monitor/focus-monitor.ts b/src/cdk/a11y/focus-monitor/focus-monitor.ts index dc1770436476..948d0b78cf87 100644 --- a/src/cdk/a11y/focus-monitor/focus-monitor.ts +++ b/src/cdk/a11y/focus-monitor/focus-monitor.ts @@ -142,7 +142,7 @@ export class FocusMonitor implements OnDestroy { }; /** Used to reference correct document/window */ - protected _document? = inject(DOCUMENT, {optional: true}); + protected _document = inject(DOCUMENT); /** Subject for stopping our InputModalityDetector subscription. */ private readonly _stopInputModalityDetector = new Subject(); @@ -206,7 +206,7 @@ export class FocusMonitor implements OnDestroy { // If the element is inside the shadow DOM, we need to bind our focus/blur listeners to // the shadow root, rather than the `document`, because the browser won't emit focus events // to the `document`, if focus is moving within the same shadow root. - const rootNode = _getShadowRoot(nativeElement) || this._getDocument(); + const rootNode = _getShadowRoot(nativeElement) || this._document; const cachedInfo = this._elementInfo.get(nativeElement); // Check if we're already monitoring this element. @@ -280,7 +280,7 @@ export class FocusMonitor implements OnDestroy { options?: FocusOptions, ): void { const nativeElement = coerceElement(element); - const focusedElement = this._getDocument().activeElement; + const focusedElement = this._document.activeElement; // If the element is focused already, calling `focus` again won't trigger the event listener // which means that the focus classes won't be updated. If that's the case, update the classes @@ -303,15 +303,9 @@ export class FocusMonitor implements OnDestroy { this._elementInfo.forEach((_info, element) => this.stopMonitoring(element)); } - /** Access injected document if available or fallback to global document reference */ - private _getDocument(): Document { - return this._document || document; - } - /** Use defaultView of injected document if available or fallback to global window reference */ private _getWindow(): Window { - const doc = this._getDocument(); - return doc.defaultView || window; + return this._document.defaultView || window; } private _getFocusOrigin(focusEventTarget: HTMLElement | null): FocusOrigin { diff --git a/src/cdk/dialog/dialog-container.ts b/src/cdk/dialog/dialog-container.ts index 038a113a028c..67a21c365cd6 100644 --- a/src/cdk/dialog/dialog-container.ts +++ b/src/cdk/dialog/dialog-container.ts @@ -82,7 +82,7 @@ export class CdkDialogContainer private _renderer = inject(Renderer2); private _platform = inject(Platform); - protected _document = inject(DOCUMENT, {optional: true})!; + protected _document = inject(DOCUMENT); /** The portal outlet inside of this container into which the dialog content will be loaded. */ @ViewChild(CdkPortalOutlet, {static: true}) _portalOutlet: CdkPortalOutlet; diff --git a/src/cdk/scrolling/viewport-ruler.ts b/src/cdk/scrolling/viewport-ruler.ts index bd477c3ede4b..66ea77dd9f79 100644 --- a/src/cdk/scrolling/viewport-ruler.ts +++ b/src/cdk/scrolling/viewport-ruler.ts @@ -36,7 +36,7 @@ export class ViewportRuler implements OnDestroy { private readonly _change = new Subject(); /** Used to reference correct document/window */ - protected _document = inject(DOCUMENT, {optional: true})!; + protected _document = inject(DOCUMENT); constructor(...args: unknown[]); diff --git a/src/cdk/text-field/autosize.ts b/src/cdk/text-field/autosize.ts index 5abb0be0f97a..f7dd3cc9f267 100644 --- a/src/cdk/text-field/autosize.ts +++ b/src/cdk/text-field/autosize.ts @@ -122,7 +122,7 @@ export class CdkTextareaAutosize implements AfterViewInit, DoCheck, OnDestroy { private _cachedScrollTop: number; /** Used to reference correct document/window */ - protected _document? = inject(DOCUMENT, {optional: true}); + protected _document = inject(DOCUMENT); private _hasFocus: boolean; diff --git a/src/material/sidenav/drawer.ts b/src/material/sidenav/drawer.ts index 7b0bfe914e34..f3b288ef7f9c 100644 --- a/src/material/sidenav/drawer.ts +++ b/src/material/sidenav/drawer.ts @@ -182,7 +182,7 @@ export class MatDrawer implements AfterViewInit, OnDestroy { private _ngZone = inject(NgZone); private _renderer = inject(Renderer2); private readonly _interactivityChecker = inject(InteractivityChecker); - private _doc = inject(DOCUMENT, {optional: true})!; + private _doc = inject(DOCUMENT); _container? = inject(MAT_DRAWER_CONTAINER, {optional: true}); private _focusTrap: FocusTrap | null = null; @@ -347,9 +347,7 @@ export class MatDrawer implements AfterViewInit, OnDestroy { constructor() { this.openedChange.pipe(takeUntil(this._destroyed)).subscribe((opened: boolean) => { if (opened) { - if (this._doc) { - this._elementFocusedBeforeDrawerWasOpened = this._doc.activeElement as HTMLElement; - } + this._elementFocusedBeforeDrawerWasOpened = this._doc.activeElement as HTMLElement; this._takeFocus(); } else if (this._isFocusWithinDrawer()) { this._restoreFocus(this._openedVia || 'program'); From 45cc05641f89afb760077cb806af9814a01909e8 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 1 Jul 2025 07:16:14 +0200 Subject: [PATCH 6/9] fix(cdk/tree): remove leaking subscription (#31457) Fixes that we weren't unsubscribing from one observable in the tree. Fixes #31454. (cherry picked from commit 69e6600647b5c98236d87843a29a69acc990065b) --- src/cdk/tree/tree.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cdk/tree/tree.ts b/src/cdk/tree/tree.ts index 497ba28d4b86..e6e485e733f5 100644 --- a/src/cdk/tree/tree.ts +++ b/src/cdk/tree/tree.ts @@ -1400,6 +1400,7 @@ export class CdkTreeNode implements OnDestroy, OnInit, TreeKeyManagerI .changed.pipe( map(() => this.isExpanded), distinctUntilChanged(), + takeUntil(this._destroyed), ) .subscribe(() => this._changeDetectorRef.markForCheck()); this._tree._setNodeTypeIfUnset(this._type); From 0a7277d37ea75aefc6705ea19b42277e1ea38d8f Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 1 Jul 2025 07:17:39 +0200 Subject: [PATCH 7/9] build: enable type checking of host bindings in docs (#31467) The docs are on a separate tsconfig so they didn't have the config that enables type checking of their host bindings. (cherry picked from commit 933bc24546ed8692306ee3778743d7a1fe6763ce) --- docs/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 0e7c0a779167..f999763b7602 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -31,6 +31,7 @@ "fullTemplateTypeCheck": true, "strictInjectionParameters": true, "strictInputAccessModifiers": true, - "strictTemplates": true + "strictTemplates": true, + "typeCheckHostBindings": true } } From 7556beaa7b20247d7c01f9e76d7097a0758f5ce7 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 1 Jul 2025 07:18:01 +0200 Subject: [PATCH 8/9] fix(material/schematics): typo in prompt question (#31449) Fixes a typo in one of the `theme-color` prompts. (cherry picked from commit 1bba607856641542993cc4068dd353796b763332) --- src/material/schematics/ng-generate/theme-color/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/material/schematics/ng-generate/theme-color/schema.json b/src/material/schematics/ng-generate/theme-color/schema.json index 6adc7d434fd6..b8e36dc8ba4e 100644 --- a/src/material/schematics/ng-generate/theme-color/schema.json +++ b/src/material/schematics/ng-generate/theme-color/schema.json @@ -49,7 +49,7 @@ "type": "boolean", "default": true, "description": "Whether to generate output file in scss or CSS", - "x-prompt": "Do you want to generated file to be a scss file? This is the recommended way of setting up theming in your application. If not, a CSS file will be generated with all the system variables defined. (Leave blank to generate a scss file)" + "x-prompt": "Do you want the generated file to be a scss file? This is the recommended way of setting up theming in your application. If not, a CSS file will be generated with all the system variables defined. (Leave blank to generate a scss file)" } } } From 09d8aa464613b3f658180e65e131d255a378c558 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Wed, 2 Jul 2025 12:19:39 -0400 Subject: [PATCH 9/9] release: cut the v20.0.5 release --- CHANGELOG.md | 17 +++++++++++++++++ package.json | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f3c68183b31..ad466a0985ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ + +# 20.0.5 "agardite-ant" (2025-07-02) +### cdk +| Commit | Type | Description | +| -- | -- | -- | +| [45cc05641](https://github.com/angular/components/commit/45cc05641f89afb760077cb806af9814a01909e8) | fix | **tree:** remove leaking subscription ([#31457](https://github.com/angular/components/pull/31457)) | +### material +| Commit | Type | Description | +| -- | -- | -- | +| [7556beaa7](https://github.com/angular/components/commit/7556beaa7b20247d7c01f9e76d7097a0758f5ce7) | fix | **schematics:** typo in prompt question ([#31449](https://github.com/angular/components/pull/31449)) | +### google-maps +| Commit | Type | Description | +| -- | -- | -- | +| [bdfeb04c3](https://github.com/angular/components/commit/bdfeb04c3a220121d7b98b9ac8147e0cfdcdfeb6) | fix | fix update schematic ([#31448](https://github.com/angular/components/pull/31448)) | + + + # 20.0.4 "strontium-shack" (2025-06-25) ### cdk diff --git a/package.json b/package.json index 2d5d8f55987a..2b6b137bce71 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "ci-notify-slack-failure": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only scripts/circleci/notify-slack-job-failure.mts", "prepare": "husky" }, - "version": "20.0.4", + "version": "20.0.5", "dependencies": { "@angular-devkit/core": "catalog:", "@angular-devkit/schematics": "catalog:",