Skip to content

RouterLinkActive initial render state prior to first router navigation #62973

Open

Description

@quentinderoubaix

Which @angular/* package(s) are relevant/related to the feature request?

router

Description

Hi team !

I wanted to open this issue to discuss your view regarding the current state of the directive RouterLinkActive and your plans regarding it.

Today, this directive has a very neat api and we strongly recommend its usage in our company.
However, the way it handles the display of the active class creates a visually annoying flicker...
You can see the flicker when you open for example https://material.angular.dev/components/categories and notice how the background around the Components button only appears after a short delay.

(Note: angular.dev does not have this behavior but the active class was managed with completely home-made code ? also, angular.dev is missing aria-current attributes for the active anchors)

For more context, there are two problems.

First one is the fact the class is added / removed through a queued microtrask.
Second is that at startup / hydration, a call to router.isActive will not be correct until the router has performed its first navigation internally...

Proposed solution

It depends greatly on what's the plan regarding Angular Routing in general...
As the team is working on turning many facets of old Angular into signals (Forms is another example), I guess Routing is in the works.

I have opened the draft PR #62974 that removed the flicker for my internal project, but it probably has a bunch of issues...

Alternatives considered

I guess copy-pasting the internal code done for angular.dev would work, but I would prefer to use something provided by @angular/router...

Activity

  1. added this to the needsTriage milestone on Aug 4, 2025
  2. atscott commented on Aug 4, 2025

    @atscott
    Contributor

    Yes, the internals of RouterLink and RouterLinkActive will be converted to signals eventually. I have a branch with this done already but current priorities prevent me from spending time on finalizing it.

    I'm not clear on how the proposed change in your PR addresses any flicker though. The state is still dependent on asynchronous router navigation. I don't believe setting the classes in a microtask would be the cause of any flicker either.

    I don't think there's anything actionable to take from this issue at the moment. If you're saying simply converting things to signals will address the problem, then perhaps this will be resolved when that's done.

  3. added
    needs reproductionThis issue needs a reproduction in order for the team to investigate further
    needs: clarificationThis issue needs additional clarification from the reporter before the team can investigate.
    on Aug 4, 2025
  4. modified the milestones: needsTriage, Backlog on Aug 4, 2025
  5. quentinderoubaix commented on Aug 4, 2025

    @quentinderoubaix
    Author

    Sorry, it seems I am not expressing myself clearly...

    Indeed, signals are not enough for the flickering thing !
    Which is why in my draft PR the isActive signal was basically this (not including contentchildren links and router events):

    readonly isActive = computed(
      () => this.router.navigated ? this.router.isActive(urlTree, options) : containsTree(this.router.parseUrl(this.location.path()), urlTree, options)
    );

    Until the Router has navigated at least once, the isActive function cannot be trusted but Location and its path can be used for the initial check.
    This felt like a really ugly workaround though...

    As a final comment, pre-rendered html from an Angular app built as a SSG would contain the correct active class, but would instantly remove it during hydration, then add it back a short while later... feels like a pity.

    Thanks for checking this issue, I am aware this is very minor in the grand scheme of things and the quantity of stuff you have to work on...

  6. atscott commented on Aug 4, 2025

    @atscott
    Contributor

    Okay, yea that makes sense. I think it's probably fair to have the RouterLInkActive eagerly assume the current path will become active when the Router hasn't yet navigated anywhere. It does irk me that navigated likely isn't the right thing to use since it gets set and reset at times that don't make sense here. We'd probably want to use something like !!router.lastSuccessfulNavigation instead.

  7. added
    P4A relatively minor issue that is not relevant to core functions
    and removed
    needs reproductionThis issue needs a reproduction in order for the team to investigate further
    needs: clarificationThis issue needs additional clarification from the reporter before the team can investigate.
    on Aug 5, 2025
  8. changed the title [-]Future of RouterLinkActive... signal-based and no flickering ?[/-] [+]RouterLinkActive initial render state prior to first router navigation[/+] on Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P4A relatively minor issue that is not relevant to core functionsarea: router

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions