chore: upgrade Angular 16 → 21 (latest)#16
Conversation
- @angular/core, @angular/cli, @angular/material → 17.x - TypeScript 4.9.5 → 5.4.5 - RxJS 6.x → 7.x - zone.js 0.13 → 0.14 - @angular-eslint/* → 17.x - @typescript-eslint/* → 7.x - angular.json deprecated options updated by migration
- @angular/core, @angular/cli, @angular/material → 18.x - Migrated from 'browser' to 'application' builder (esbuild) - HttpClientModule replaced with provideHttpClient() (automated migration) - Fixed moment.js namespace imports to default imports (esbuild compat) - Synced Bootstrap glyphicon fonts to fix duplicate output file error - esModuleInterop enabled in tsconfig.json
- @angular/core, @angular/cli, @angular/material → 19.x - TypeScript 5.4.5 → 5.8.3 - zone.js 0.14 → 0.15 - @angular-eslint/* → 19.x - All components explicitly marked standalone: false (Angular 19 default change) - Standalone is now default in Angular 19
- @angular/core, @angular/cli, @angular/material → 20.x - @angular-eslint/* → 20.x - Node.js requirement bumped to v20+ (now using Node 22) - moduleResolution changed from 'node' to 'bundler' in tsconfig.json - TestBed.get() replaced with TestBed.inject() (deprecated API migration) - Templates migrated to new control flow syntax (@if, @for, @switch) - Workspace generation defaults updated for v20 style guide
- @angular/core, @angular/cli, @angular/material → 21.x - @angular-eslint/* → 21.x - TypeScript 5.8.3 → 5.9.3 - tsconfig lib updated from es2017 to es2022 - Bootstrap migrated to use provideZoneChangeDetection() in main.ts - Deprecated bootstrap options migrated to providers
- Removed deprecated deps: codelyzer, protractor, @types/jasminewd2, core-js, karma-coverage-istanbul-reporter - Updated devDependencies: @typescript-eslint/* → 8.x, @types/jasmine → 5.1, @types/node → 22.x, jasmine-core → 5.1, karma → 6.4, karma-coverage added - Replaced polyfills.ts with zone.js direct reference in angular.json - Removed useDefineForClassFields: false from tsconfig (deprecated in Angular 20+) - Updated module to es2022 in tsconfig - Removed protractor e2e project from angular.json - Removed createDefaultProgram and e2e/tsconfig.json from .eslintrc.json - Replaced deprecated @typescript-eslint/quotes with built-in quotes rule - Migrated constructor injection to inject() function (Angular 21 best practice) - Removed backwards-compatible constructor overloads - All lint checks pass
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| } @if (description.dirty && description.hasError('maxlength')) { | ||
| <span class="help-block">Description may be at most 255 charaters long</span> | ||
| } | ||
| @if (description.dirty && description.hasError('maxlength')) { | ||
| <span class="help-block">Description may be at most 255 characters long</span> | ||
| } @if (description.dirty && description.hasError('maxlength')) { | ||
| <span class="help-block">Description may be at most 255 charaters long</span> | ||
| } |
There was a problem hiding this comment.
🔴 Duplicate maxlength validation messages with typos in visit-edit template
The *ngIf to @if migration preserved pre-existing duplicate maxlength validation blocks for the description field. When a user triggers the maxlength error, three error messages are displayed instead of one: two with the misspelling "charaters" (lines 71, 76) and one with correct spelling (line 74). The old code had these duplicates crammed onto single lines (which was already buggy), and the migration mechanically converted each *ngIf span into a separate @if block, making the duplication explicit. Only one @if block for maxlength should remain, with the correct spelling "characters".
| } @if (description.dirty && description.hasError('maxlength')) { | |
| <span class="help-block">Description may be at most 255 charaters long</span> | |
| } | |
| @if (description.dirty && description.hasError('maxlength')) { | |
| <span class="help-block">Description may be at most 255 characters long</span> | |
| } @if (description.dirty && description.hasError('maxlength')) { | |
| <span class="help-block">Description may be at most 255 charaters long</span> | |
| } | |
| } | |
| @if (description.dirty && description.hasError('maxlength')) { | |
| <span class="help-block">Description may be at most 255 characters long</span> | |
| } |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Upgrades the Angular PetClinic app from Angular 16.2.1 to Angular 21.2.11 (latest), stepping through each major version (16→17→18→19→20→21) using official
ng updateschematics. All breaking changes have been resolved and the app builds and lints cleanly.Key changes
browser)application)*ngIf/*ngFor@if/@forinject()functionHttpClientModuleprovideHttpClient()Breaking changes handled
browser→applicationbuilder (esbuild)standalone: falseadded to all NgModule-based components*ngIf/*ngForto@if/@forinject()functionFull details in
BREAKING_CHANGES.md.Review & Testing Checklist for Human
npm install && npx ng buildlocally to verify the build succeeds on your environmentowner-list.component.html) to confirm@if/@forsyntax is correctprovideHttpClient()BREAKING_CHANGES.mdfor completenessNotes
@angular-eslint/prefer-standalonerule is disabled since a full standalone migration is a separate effort.polyfills.tsfile still exists on disk but is no longer referenced byangular.json(polyfills are now["zone.js"]).Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/a97c861fddb84e01a556bde7e1c55145