Solvedangular routerLinkActive not updating when routerLink changed

I have a routerLink URL that can change over time, but when the URL changes, routerLinkActive is not re-evaluated.

I'm submitting a...

[ ] Regression (a behavior that used to work and stopped working in a new release)
[ x ] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Change a routerLink URL to match/not match the current URL. routerLinkActive class is not applied/removed.

Expected behavior

routerLinkActive is re-evaluated when its corresponding routerLink is updated.

Minimal reproduction of the problem with instructions

Click "link a" or "link b" to make them active, then click the switchLinks button to change the URLs. Nothing changes.
http://plnkr.co/edit/DHn4my9uAKJSIQSTIm1g?p=preview

What is the motivation / use case for changing the behavior?

I have multiple departments managed by the same UI, with department name as a variable in the URL. When the user switches departments, and the on screen links or URL is changed, the UI doesn't update the routerLinkActive.

I think it's because ContentChildren.changes doesn't fire if the contents of a directive is changed, only when directives are added or removed.:
https://github.com/angular/angular/blob/master/packages/router/src/directives/router_link_active.ts#L106

Maybe it's too bad for performance to fix this?

Environment

Angular version: 4.3
Mac

Browser:

  • [x ] Chrome (desktop) version 59
  • Chrome (Android) version XX
  • Chrome (iOS) version XX
  • Firefox version XX
  • Safari (desktop) version XX
  • Safari (iOS) version XX
  • IE version XX
  • Edge version XX
29 Answers

✔️Accepted Answer

I have a hack that seems to work. After looking at the source code, it looks like this.update() is also called any time the inputs are changed. So, if you add an routerLinkActiveOptions property and give it a throw-away value that is changed based on the URL, then the inputs will technically change. Example:

<a
routerLink="/foo/:id/bar"
routerLinkActive="on"
[routerLinkActiveOptions]="{ exact: false, __change_detection_hack__: id }"> Link </a>

Here, the __change_detection_hack__ key will change when the id changes (ie, after navigation has completed and the template is reconciled), which will cause the inputs to change, which will cause the this.update() method to run. And, at that point, the QueryList<RouterLink> should be in the proper state.

It's janky, but it works as a stop-gap.

Other Answers:

Hello Angular guys, @vsavkin, @petebacondarwin, @vicb, @IgorMinar, @tbosch, @gkalpak.

Are you going to fix this once for all?

Developers should not do hacks for such a basic functionality :D

Best, Miroslav

Still having this issue in Angular 9

I just ran into this as well. I have a tab setup where the tab links to a child like:

<a routerLink="/tabs/{{ id }}/build" routerLinkActive="on">build</a>

... and if I navigate from /tabs/1/build to /tabs/2/build, the "build" tab active-class turns off, despite the fact that the URL changes to reflect the new id. Note that it doesn't matter how the navigation takes place: performing it programmatically or just manually editing the URL -- the effect is the same.

More Issues: