angular: RouterLinkActive Causes Browser To Freeze When Inside NgFor

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

There seems to be some sort of infinite loop occurring in the Angular code when a “routerLinkActive” directive is placed within an *ngFor container. This loop completely locks up the browser and makes the application unusable.

Expected behavior

The routerLinkActive directive should work inside an *ngFor construct.

Minimal reproduction of the problem with instructions

http://plnkr.co/edit/Q7kzTjDMdehSVmQbSBNS

  1. Go to the above plunkr
  2. Observe that both routes work (click on the Path1 and Path2 links)
  3. Go to src/app.ts
  4. Add routerLinkActive=“active” to the following line: <a *ngFor="let page of pages" [routerLink]="page.path" >{{page.name}}</a>

Then when the plunkr refreshes, note that it completely locks up. For my current application, it is completely locking up in an infinite loop.

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

This makes my application unusable and I’ll have to create a work-around rather than use the provided directive.

Environment


Angular version: 5.1.1


Browser:
- [x ] Chrome (desktop) version XX
- [ ] 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
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 16 (4 by maintainers)

Most upvoted comments

@ziaulain In my above example, you can manually attach a CSS class called “active”, and pass the object to a function, like this:

<a *ngFor="let page of pages" [routerLink]="page.path [class.active]="isActivePage(page)" >{{page.name}}</a>

Then, inject the angular router into your component:

import { Router } from "@angular/router";

...

constructor(private _router: Router) {
...
}

Finally, implement the “isActivePage” method in your component:

public isActivePage(page: any): boolean {
        
        let isActive = false;

        if (page.path === this._router.url) {
            isActive = true;
        }

        return isActive;
 }

Ideally, you would have the “page” defined as a type, rather than an “any” type, but this is just a simple example of what you can do…

I ran into this issue, same cause. Angular compares instances of objects to determine if they’ve changed when checking to see if it needs to regenerate the page. Sometimes I forget this and generate new instances every call for the routerLink value, which is what I and OP seem to have been doing to produce this bug.

I would say this is not technically a bug, but a side effect of the way Angular works.

However it should not result in an infinite loop The message that normally appears in the console when Angular detects that property values are improperly changing between fetches is expected instead. However, even in cases where the infinite loop does not happen, this message does not appear. I would say that and the infinite loop are the bugs here.

Another side effect of doing this if you DO NOT use routerLinkActive, is routerLink attributes will generate proper links in the browser status bar on hover, but clicking them does nothing.

@bmbell Your problem is that your pages property returns a new array with each invocation. If you change that your sample works flawless.

https://stackblitz.com/edit/angular-omltpp?file=src%2Fapp%2Fapp.component.ts

@mart2k @NeilAttewell Reproduction?

Page freezes in v11.2.4

EDIT: links were passed by a getter. Changed it to a property and the page no longer crashes