Skip to content

Conversation

@lindolo25
Copy link
Contributor

@lindolo25 lindolo25 commented Dec 12, 2025

Hi @wawyed! This PR implements support for v21 and fixes a recent bug I notice, specific for zoneless apps. I decided to add these changes together to take the least of your time. If instead you will like for me to treat it as 2 separate changes, I'll be happy to split the changes and create merge request individually.

More about the changes:

  • Angular v21 support.
  • Added downstream test projects for zoneless applications.
  • Changes to UIView that introcudes @if as replacement for *ngIf directive (currently deprecated) and signals specifically for the _componentRef property of the class.
  • Added test suites that for the specific scenario of the bug. It involved add test environments configured to use zoneless.

About the bug: It is only reproducable for applications configure with zoneless change detection or for UIView's instances hosted by a component configured with change detection strategy onPush. It involves the projected content of UIViews. here is an example of the components configuration.

@Component({
  selector: 'app-root',
  imports: [UIView, AnchorUISref, UISref],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <h1>Hello from {{ name }}!</h1>
    <ui-view>
      <a uiSref="root.child">follow this link to open the child state</a>
    </ui-view>
  `,
})
export class AppComponent {
  name = 'UIView Zoneless bug demo';
}

@Component({
  selector: 'app-child',
  imports: [UISref, AnchorUISref],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <a uiSref="^">Use this link to go back</a>
    <p>Use the browser's back button to reproduce the bug.</p>
  `,
})
export class AppChildComponent {}

export const routes: Ng2StateDeclaration[] = [
  {
    name: 'root',
    url: '/home',
    component: AppComponent,
  },
  {
    name: 'root.child',
    url: '/child',
    component: AppChildComponent,
  },
];

bootstrapApplication(UIView, {
  providers: [
    provideZonelessChangeDetection(),
    provideUIRouter({
      states: routes,
      otherwise: '/home',
    }),
  ],
});

Steps to reproduce:

  1. use the link in the /home page to navigate to the child state. the AppChildComponent will replace the content for UIView.
  2. use the link in the /child page to go back to /home. All works fine so far, the projected content for the UIView is restored.
  3. use the browser's back button to go back. The projected content is not restored.

Here are a few links to working examples of this bug:

Another topic:

The merge request for sample-app-angular that added support for v20 was never merge. I'll be adding a new PR with support for v21. ui-router/sample-app-angular#795

Fixes #1010

versions for other packages as needed for peer dependency requirements
v21. this needs to be done in a separeted step as the cli requires for
the git chnages to be cleared before updating packages.
_componentRef to be a readonly signal and updating
ChangeDetectionStrategy to onPush. This fixes issue restoring the
projected content when navigating from a child state to a state with
projected content.
the global test to run both zone and zoneless test suites.
@lindolo25
Copy link
Contributor Author

Hi @wawyed and @christopherthielen, I updated this PR with the recent changes to main, it is ready for review. thanks again for your time and Happy new year!

@christopherthielen
Copy link
Member

I'll take a look, thanks for the PR!

Note: I'm not longer using or tracking the Angular project, but I've been updating a bunch of other ui-router packages recently, trying to modernize and consolidate tooling.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds Angular v21 support and fixes a bug affecting projected content restoration in UIView components when using zoneless change detection or OnPush change detection strategy. The fix replaces the deprecated *ngIf directive with Angular's @if control flow and converts _componentRef to a signal to ensure proper change detection.

Key changes:

  • Upgraded to Angular v21 and TypeScript 5.9 across all test projects and dependencies
  • Fixed UIView projected content restoration bug by converting _componentRef to a signal and using @if instead of *ngIf
  • Added comprehensive test coverage for zoneless applications including new test suites and downstream projects

Reviewed changes

Copilot reviewed 43 out of 76 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/directives/uiView.ts Fixed bug by converting _componentRef to signal and replacing *ngIf with @if
test/uiView/viewIsRestored.spec.ts Added test suite for projected content restoration
test-zoneless/uiView/viewIsRestored.spec.ts Added zoneless-specific test suite for the bug fix
test-zoneless/setupJest.ts Setup for zoneless test environment
test-zoneless/tsconfig.spec.json TypeScript config for zoneless tests
package.json Updated dependencies to Angular v21 and split test scripts
test-angular-versions/v21/* New test project for Angular v21
test-angular-versions/v21-zoneless/* New test project for Angular v21 zoneless
test-angular-versions/v21-standalone/* Updated standalone test project to v21
test-typescript-versions/typescript5.9/* Added TypeScript 5.9 test project
downstream_projects.json Updated downstream project references

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

expect(h2Elelement).toBeFalsy();
});

it("should the child component", async () => {
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

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

Corrected test description from 'should the child component' to 'should show the child component'.

Suggested change
it("should the child component", async () => {
it("should show the child component", async () => {

Copilot uses AI. Check for mistakes.
expect(h2Elelement).toBeFalsy();
});

it("should the child component", async () => {
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

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

Corrected test description from 'should the child component' to 'should show the child component'.

Suggested change
it("should the child component", async () => {
it("should show the child component", async () => {

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,27 @@
# v21-zoneless

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 20.0.5.
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

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

The README states the project was generated with Angular CLI version 20.0.5, but this is a v21-zoneless project. Update the version number to match the project version (e.g., 21.0.2 based on package.json).

Suggested change
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 20.0.5.
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 21.0.2.

Copilot uses AI. Check for mistakes.
# V20-standalone
# V21-standalone

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 20.0.5.
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

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

The README states the project was generated with Angular CLI version 20.0.5, but this is a v21-standalone project. Update the version number to match the project version (e.g., 21.0.2 based on package.json).

Suggested change
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 20.0.5.
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 21.0.2.

Copilot uses AI. Check for mistakes.
@christopherthielen
Copy link
Member

Well, this all looks great and I see no blockers. @wawyed I'm going to merge this and start the release process

@christopherthielen christopherthielen merged commit c005e01 into ui-router:master Jan 3, 2026
4 checks passed
christopherthielen added a commit that referenced this pull request Jan 3, 2026
@christopherthielen
Copy link
Member

@lindolo25 @wawyed please try this when you can and report any problems

@lindolo25
Copy link
Contributor Author

Hi @christopherthielen, thanks for the help with this PR.

I'll take a look, thanks for the PR!

Note: I'm not longer using or tracking the Angular project, but I've been updating a bunch of other ui-router packages recently, trying to modernize and consolidate tooling.

If you like any help, let me know! I also wanted to ask if it is possible for the documentation to be updated for https://ui-router.github.io. I look at the build process as configured in several of the projects and I think there was an error with the typescript version being incompatible in the Docs container image and the angular project. I can take a look again and create a PR!

@christopherthielen
Copy link
Member

The docgen system seems rather broken at the moment. If you can get it working again, that would be awesome.

I do have a dream to modernize all the depts of the whole ui router ecosystem and then converge everything into a monorepo. At that point it would be worth looking into different docs paradigm.

That's a lot though, and may never happen. So if we can resurrect the existing docgen, it would be very useful.

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.

Bump Versioning to Match supported Angular version?

2 participants