angular: RouterLink generation throws exception on parameters not yet present

I’m submitting a … (check one with “x”)

[ ] bug report [X ] feature request [ ] support request

Current behavior The following snippet used to work in router v2, when the user is initialized as an empty object , but don’t hold id and'name. A scenario for this would be when the user is resolved asynchronously. <a [routerLink]="['/user',user.id]">{{user.name}}</a>

The console logs the following now in v3.0.0-beta.2:

browser_adapter.js:84 TypeError: Cannot read property 'toString' of undefined
    at getPath (http://127.0.0.1:3000/vendor.bundle.js:61185:24)
    at prefixedWith (http://127.0.0.1:3000/vendor.bundle.js:61241:21)
    at updateSegment (http://127.0.0.1:3000/vendor.bundle.js:61202:14)
    at updateSegmentChildren (http://127.0.0.1:3000/vendor.bundle.js:61224:33)
    at Object.createUrlTree (http://127.0.0.1:3000/vendor.bundle.js:61083:10)
    at Router.createUrlTree (http://127.0.0.1:3000/vendor.bundle.js:20669:35)
    at RouterLinkWithHref.updateTargetUrlAndHref (http://127.0.0.1:3000/vendor.bundle.js:32176:37)
    at RouterLinkWithHref.ngOnChanges (http://127.0.0.1:3000/vendor.bundle.js:32164:75)
    at DebugAppView._View_ShowEventsComponent0.detectChangesInternal (ShowEventsComponent.template.js:283:59)
    at DebugAppView.AppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55473:15)
    at DebugAppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55578:45)
    at DebugAppView.AppView.detectViewChildrenChanges (http://127.0.0.1:3000/vendor.bundle.js:55499:20)
    at DebugAppView.AppView.detectChangesInternal (http://127.0.0.1:3000/vendor.bundle.js:55484:15)
    at DebugAppView.AppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55473:15)
    at DebugAppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55578:45)
    at DebugAppView.AppView.detectContentChildrenChanges (http://127.0.0.1:3000/vendor.bundle.js:55491:20)
    at DebugAppView.AppView.detectChangesInternal (http://127.0.0.1:3000/vendor.bundle.js:55483:15)
    at DebugAppView.AppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55473:15)
    at DebugAppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55578:45)
    at DebugAppView.AppView.detectViewChildrenChanges (http://127.0.0.1:3000/vendor.bundle.js:55499:20)
    at DebugAppView._View_ClubDelegate_Host0.detectChangesInternal (ClubDelegate.template.js:31:8)
    at DebugAppView.AppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55473:15)
    at DebugAppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55578:45)
    at DebugAppView.AppView.detectContentChildrenChanges (http://127.0.0.1:3000/vendor.bundle.js:55491:20)
    at DebugAppView._View_SportsbyMainComponent0.detectChangesInternal (SportsbyMainComponent.template.js:246:8)
    at DebugAppView.AppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55473:15)
    at DebugAppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55578:45)
    at DebugAppView.AppView.detectViewChildrenChanges (http://127.0.0.1:3000/vendor.bundle.js:55499:20)
    at DebugAppView.AppView.detectChangesInternal (http://127.0.0.1:3000/vendor.bundle.js:55484:15)
    at DebugAppView.AppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55473:15)
    at DebugAppView.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:55578:45)
    at ViewRef_.detectChanges (http://127.0.0.1:3000/vendor.bundle.js:41719:66)

If I initialize the user object in the component with a dummy id like this user={id:1} everything works fine.

Expected/desired behavior The router refuses to create a (href) link on the respective element, but does return silently without throwing an exception.

What is the motivation / use case for changing the behavior? To avoid to implement (many) ngIf directives to check if ansynchronously resolved objects are present or dummy initializations with dummy properties.

Please tell us about your environment:

  • Angular version: 2.0.0-rc.4, router v3.0.0-beta2
  • Browser: Chromium 51.0.2704.79 , FF v47, both on Linux Mint
  • Language: TypeScript compiled to ES5

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 2
  • Comments: 15 (6 by maintainers)

Most upvoted comments

@akirasosa @st0nie I confirmed that this is a bug. You can also write routerLinks as one long string, so the following will work also.

<a [routerLink]="['/product-editor/' + product.id]">Edit product</a>

I don’t understand why this is closed since the ‘?’ operator doesn’t work, What I’m missing?

Doesn’t work:

<a [routerLink]="['/preview/referral/', report?.referral?.id]">#{{ report?.referral?.id }}</a>

But this, that I understand it is the workaround, works

<a [routerLink]="['/preview/referral/' + report?.referral?.id]">#{{ report?.referral?.id }}</a>

Thanks

Could please someone help?

I have the following code:

<div class="menu">
  <ul>
    <li>
      <a routerLink="{{contract?.id}}/Customers" routerLinkActive="active">Letztverbrauch</a>
    </li>    
  </ul>
</div>

And I get the following error:

TypeError: Cannot read property ‘subscribe’ of undefined at new RouterLinkWithHref

contract is a @Input() property.

@Component({
  selector: "app-menu",
  templateUrl: "./menu.component.html",
  styleUrls: ["./menu.component.scss"]
})
export class MenuComponent {

  @Input() public contract: Contract;

  constructor() { }

}

I have encountered the same problem in migrating deprecated router.

@brandonroberts I tried it, but got TypeError: Cannot read property 'toString' of null, though it worked in deprecated router. Still have not found any workaround…

Have you tried using the safe-navigation operator?

<a [routerLink]="['/user', user?.id]">{{ user?.name }}</a>