Skip to content

feat: Upgrade Angular from 16.2.1 to 21.2.8#7

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1776087761-upgrade-angular-latest
Open

feat: Upgrade Angular from 16.2.1 to 21.2.8#7
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1776087761-upgrade-angular-latest

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Apr 13, 2026

Summary

Multi-step Angular upgrade across 5 major versions (16 → 17 → 18 → 19 → 20 → 21), performed using ng update schematics at each step. Key migrations applied:

  • Build system: browser builder → application builder (angular.json)
  • HTTP client: HttpClientModuleprovideHttpClient(withInterceptorsFromDi()) (13 files)
  • Standalone default: Added explicit standalone: false to all components (24 files)
  • Control flow: *ngIf/*ngFor/*ngSwitch@if/@for/@switch block syntax (19 templates)
  • Testing: TestBed.get()TestBed.inject() (4 spec files)
  • TypeScript: moduleResolution: "node""bundler", added esModuleInterop: true
  • Bootstrap: main.ts updated with provideZoneChangeDetection() provider

Manual fixes applied after automated migrations:

  • Moment.js: import * as momentimport moment from 'moment' (4 files) to fix build error with bundler moduleResolution
  • Removed duplicate bootstrap.css from angular.json styles — the application builder's CSS url() resolution conflicted with the project's custom petclinic.css (which already bundles Bootstrap 3.3.7), producing a duplicate glyphicons-halflings-regular.svg build error

All breaking changes are documented in BREAKING_CHANGES.md.

Package Before After
@angular/core 16.2.1 21.2.8
@angular/material 16.2.1 21.2.6
TypeScript 4.9.5 5.9.3
zone.js ~0.13.1 ~0.15.1

Review & Testing Checklist for Human

  • Visual regression from bootstrap CSS removal: node_modules/bootstrap/dist/css/bootstrap.css was removed from both build and test style arrays in angular.json. The assumption is that src/assets/css/petclinic.css already includes the full Bootstrap 3.3.7 CSS. Run the app and visually inspect all pages to confirm no styling is broken (especially glyphicons, grid layout, and form controls).
  • Duplicate validation blocks in visit-edit.component.html: The automated control flow migration faithfully converted pre-existing duplicate *ngIf blocks for description.hasError('maxlength') — there are now three @if (description.dirty && description.hasError('maxlength')) blocks (one with typo "charaters", one correct, one more with typo). This is a pre-existing bug carried forward, but worth cleaning up.
  • @angular-eslint packages still at v16: These were not upgraded and the lint output warns about unsupported TypeScript version (5.9.3 vs supported <5.2.0). Lint passes today but may produce incorrect results. Consider upgrading these separately.
  • Smoke test the running app: Start the dev server (ng serve) with the backend API running and verify core flows — owner list, add/edit pet, add/edit visit — especially date picker interactions (moment.js import change).

Notes

  • ng build completes successfully.
  • ng lint passes (after auto-fixing quote style in main.ts).
  • RxJS was intentionally left at ^6.3.1 — the schematics did not require an upgrade.
  • The @angular-eslint packages (v16) are a known mismatch that should be upgraded in a follow-up.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/88b1acc5d0b14da0b05cb14ab0044d78


Open with Devin

- Upgrade Angular Core/CLI: 16.2.1 -> 21.2.8
- Upgrade Angular Material/CDK: 16.2.1 -> 21.2.6
- Upgrade TypeScript: ~5.1.6 -> 5.9.3
- Migrate HttpClientModule to provideHttpClient() (Angular 18)
- Add standalone:false to all non-standalone components (Angular 19)
- Migrate to application builder from browser builder (Angular 19)
- Convert *ngIf/*ngFor/*ngSwitch to block control flow syntax (Angular 20)
- Replace TestBed.get() with TestBed.inject() (Angular 20)
- Update moduleResolution to bundler (Angular 20)
- Migrate bootstrap options to providers (Angular 21)
- Fix moment.js namespace imports to default imports
- Remove duplicate bootstrap CSS from angular.json
- Document all breaking changes in BREAKING_CHANGES.md
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment on lines +68 to +77
@if (description.dirty && description.hasError('minlength')) {
<span class="help-block">Description must be at least 1 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>
} @if (description.dirty && description.hasError('maxlength')) {
<span class="help-block">Description may be at most 255 charaters long</span>
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Triple duplicate maxlength error messages in visit-edit template

The @for/@if migration from *ngIf preserved a pre-existing duplication bug and made it worse. When a user triggers a maxlength validation error on the description field, three error messages are displayed simultaneously: two reading "Description may be at most 255 charaters long" (with typo "charaters") at lines 70-71 and 75-76, and one correct message at lines 73-74. The old code had these duplicates crammed onto two long lines (src/app/visits/visit-edit/visit-edit.component.html:64-65 in the old version), and the mechanical migration expanded them into three separate @if blocks without deduplication.

Suggested change
@if (description.dirty && description.hasError('minlength')) {
<span class="help-block">Description must be at least 1 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>
} @if (description.dirty && description.hasError('maxlength')) {
<span class="help-block">Description may be at most 255 charaters long</span>
}
@if (description.dirty && description.hasError('minlength')) {
<span class="help-block">Description must be at least 1 characters long</span>
}
@if (description.dirty && description.hasError('maxlength')) {
<span class="help-block">Description may be at most 255 characters long</span>
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants