Upgrade Angular 20 → 21 (LTS) stepped upgrade - #734
Merged
Conversation
Steps the library and test-app harness from Angular 20 to Angular 21 via the supported ng update path, per ADR-0001's epic target. - Bump root peer deps to @angular/*@^21.2.23, @angular/cli@^21.2.24, zone.js@^0.16.0, angular-eslint@21.4.0, typescript@5.9.3; move @fortawesome/angular-fontawesome ~3.0.0 -> ~4.0.0 (only version with an Angular 21 peer). Package version -> 21.0.0. - Bump test-app harness to @angular/*@21.2.23, @angular/cli@21.2.24, @angular/cdk@21.2.14, @angular-builders/custom-esbuild@21.1.0, @analogjs/vite-plugin-angular/vitest-angular@2.7.2, zone.js@0.16.3, typescript@5.9.3; pin vite@6.4.2 explicitly. - Apply ng update migrations: main.ts bootstrap now passes applicationProviders: [provideZoneChangeDetection()]; tsconfig.json drops the redundant lib override. - Fix removed/changed CDK & core APIs: tab-body/tab-label move off PortalHostDirective/TemplatePortalDirective/cdkPortalHost (removed in CDK 21) onto CdkPortalOutlet/CdkPortal/cdkPortalOutlet; data-table drops the _VIEW_REPEATER_STRATEGY provider (no longer exported by @angular/cdk/collections); fieldset/label-wrapper window:resize handlers now accept the $event parameter. - Restore zone-based change detection globally in test-setup.ts via provideZoneChangeDetection(), since Angular 21 defaults TestBed to zoneless CD, which broke the majority of existing specs with ExpressionChangedAfterItHasBeenCheckedError on a second detectChanges() call after a bound-property mutation. Closes #575
There was a problem hiding this comment.
🟡 Changes recommended
The resize fixes introduce unnecessary public signature changes, and the migrated custom-label portal path lacks focused coverage.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Upgrades the raw-source library and test harness from Angular 20 to Angular 21 while adapting removed CDK APIs and preserving zone-based behavior.
Changes:
- Updates Angular, CDK, TypeScript, Zone.js, and supporting tooling.
- Migrates portal and table integrations for CDK 21.
- Restores zone-based test and application bootstrapping behavior.
File summaries
| File | Description |
|---|---|
package.json |
Updates library version and peer/tooling dependencies. |
test-app/package.json |
Upgrades the Angular test harness dependencies. |
test-app/tsconfig.json |
Removes the redundant library override. |
test-app/src/main.ts |
Enables zone-based change detection at bootstrap. |
test-app/src/test-setup.ts |
Restores zone-based TestBed behavior globally. |
src/ui-kit/components/data-table/data-table.component.ts |
Removes the obsolete view-repeater provider. |
src/ui-kit/experimental/tabs/tab-body.ts |
Migrates to CdkPortalOutlet. |
src/ui-kit/experimental/tabs/tab-body.html |
Updates the portal outlet selector. |
src/ui-kit/experimental/tabs/tab-label.ts |
Migrates to CdkPortal. |
src/ui-kit/experimental/tabs/tab-group.html |
Updates custom-label portal rendering. |
src/ui-kit/wrappers/fieldset-wrapper/fieldset-wrapper.component.ts |
Adjusts resize-listener handling. |
src/ui-kit/wrappers/label-wrapper/label-wrapper.component.ts |
Adjusts resize-listener handling. |
Review details
- Files reviewed: 12/14 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- fieldset-wrapper/label-wrapper: revert onResize() to a zero-argument @HostListener('window:resize') instead of adding a required $event parameter, matching the existing page.component.ts precedent and avoiding an unnecessary public signature change for deep-import consumers. - tab-group.spec.ts: add a focused test rendering an <ng-template sam-tab-label> to exercise the CdkPortalOutlet / MdTabLabel migration path, which was previously untested.
fpigeonjr
marked this pull request as ready for review
September 11, 2026 21:10
The library runs on Vitest, not Jasmine/Karma, and no source file references Jasmine globals. Drops the stale @types/jasmine devDependency and the 'jasmine' entry from tsconfig.json's compilerOptions.types.
divyabairavarasu
approved these changes
Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Steps the library from Angular 20 to Angular 21 (LTS) via the supported
ng updatepath, bumping thetest-appharness to Angular 21 in lockstep, per ADR-0001's epic target.package.json): peer deps bumped to@angular/*@^21.2.23,@angular/cli@^21.2.24,zone.js@^0.16.0,angular-eslint@21.4.0,typescript@5.9.3.@fortawesome/angular-fontawesomemoved~3.0.0→~4.0.0(the only published version with an Angular 21 peer). Package version bumped to21.0.0.test-appharness:@angular/*@21.2.23,@angular/cli/build-angular@21.2.24,@angular/cdk@21.2.14,@angular-builders/custom-esbuild@21.1.0,@analogjs/vite-plugin-angular/vitest-angular@2.7.2,zone.js@0.16.3,typescript@5.9.3, and an explicitvite@6.4.2pin (previously only enforced viaoverrides).ng updatemigrations applied:test-app/src/main.tsbootstrap now passesapplicationProviders: [provideZoneChangeDetection()];test-app/tsconfig.jsondropped the redundantliboverride.tab-body.ts/tab-label.ts/ their templates:PortalHostDirective,TemplatePortalDirective, and thecdkPortalHostselector (all removed in CDK 21) replaced withCdkPortalOutlet/CdkPortal/cdkPortalOutlet.data-table.component.ts: dropped the_VIEW_REPEATER_STRATEGY/_DisposeViewRepeaterStrategyprovider, which is no longer exported from@angular/cdk/collections—CdkTablenow selects its own repeater strategy internally.fieldset-wrapper.component.ts/label-wrapper.component.ts:@HostListener("window:resize", ["$event"])handlers now accept the$eventparameter (Angular 21 no longer tolerates an argument-count mismatch here).test-app/src/test-setup.ts: Angular 21 changedTestBed's default change-detection strategy to zoneless, which broke the majority of existing specs withExpressionChangedAfterItHasBeenCheckedErroron any seconddetectChanges()call following a bound-property mutation (previously legal, zone-based behavior). Restored zone-based change detection globally via abeforeEachthat providesprovideZoneChangeDetection(), preserving pre-21 spec semantics without touching every spec file individually.Motivation and Context
Parent epic: #562 (Jira: IAEMOD-61187). Unblocked by #574 (Angular 19 → 20 upgrade), which is closed.
Closes #575
Type of Change (Select One and Apply Label)
bugfixlabelenhancementlabelbreakinglabelmaintenancelabelHow to Test
npm ci && npm ci --prefix test-appnpm --prefix test-app test— confirm all 155 spec files / 1424 tests passnpm run coverage:check— confirm coverage stays at/above the ratcheted floornpm --prefix test-app run build— confirm the harness still builds (pre-existing Sass@importdeprecation warnings are expected and unrelated)npm run lint && npm --prefix test-app run lint— confirm no new lint errors and warnings stay within baselinenpm run format:check— confirm formatting is cleannpm run validate:publish— confirmsnpm pack --dry-runsucceeds and all frozen deep-import paths (scripts/consumer-deep-imports.json) still resolveExpected result: All commands above exit 0; the test suite reports
155 passed (155)files /1424 passed (1424)tests.Screenshots (if appropriate)
N/A — dependency upgrade and internal API-compat fixes only, no visual changes.
Checklist
gh-<number>-<slug>)format:checkpasses (npm run format:check)lintpasses (npm run lint)buildpasses (cd test-app && npm run build)cd test-app && npm test)