Angular 4 - routerLinks without start slash are overwritten after an uncaught error

This is a continuation of Angular 4 + zonejs: routing stops working after an uncaught error because we had a difficult integration of the proposed changes into our project.

The reason for this can be seen in this adapted plunker https://embed.plnkr.co/oUE71KJEk0f1emUuMBp8/ in app.html:

In our project, routerLinks does not prefix the slash "/". This disrupts all navigation after moving to another section after visiting the "Error Component". All links correspond with the current path, for example. home.

Adding a slash to the routerLink attributes corrects this behavior.

Why is this?

And is there any documentation / specification regarding this?

We found this Angular ticket and api for the RouterLink directive , which says

or does not start with a slash, the router will instead look at the children of the currently activated route.

But how does this relate to what happens with the uncaught error, respectively, with the proposed workaround from the previous question?

+3
source share
1 answer

After a navigation error, the routing state is restored

this.currentRouterState = storedState;
this.currentUrlTree = storedUrl;

https://github.com/angular/angular/blob/4.1.2/packages/router/src/router.ts#L750-L751

createUrlTree startPosition:

function findStartingPosition(nav, tree, route) {
    if (nav.isAbsolute) { // it will be executed when you use `/` in routeLink
        return new Position(tree.root, true, 0);
    }
    if (route.snapshot._lastPathIndex === -1) { // without '/'
        return new Position(route.snapshot._urlSegment, true, 0);
    }
    ...
}

, routeLinks, tree.root, .

UrlTree (oldSegmentGroup )

function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) {
    ...
    if (urlTree.root === oldSegmentGroup) { // will be false after the error
        return new UrlTree(newSegmentGroup, qp, fragment);
    }
    return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), qp, fragment);
}

:

RouteReuseStrategy.

let erroredUrlTree;
let erroredState;

export class AppModule {
  constructor(private router: Router) {
    router.events.subscribe(function (e) {
      if(e instanceof  NavigationError ) {
        erroredState = (router as any).currentRouterState;
        erroredUrlTree =  (router as any).currentUrlTree;
      }
    });
  }
}

:

@Injectable()
export class MyErrorHandler implements ErrorHandler {
  constructor(private inj: Injector) {}

  handleError(error: any): void {
    console.log('MyErrorHandler: ' + error);
    if(erroredUrlTree) {
      let router: any = this.inj.get(Router);
      router.currentRouterState = erroredState;
      router.currentUrlTree = erroredUrlTree;
      erroredState = null;
      erroredUrlTree = null;
    }
  }
}

Plunker

, , , ,

+1

Source: https://habr.com/ru/post/1017110/


All Articles