Search code examples
angularangular-router

Navigate to parent path from router outlet (NG5)


Problem

Trying to navigate from http://localhost:4200/#/place/(popup:tabs-modal) (an outlet) to http://localhost:4200/#/place/someId

Notice that the outlet is basically a child route to "place".

What I can do

I can close the outlet, and just end up on: http://localhost:4200/#/place: this.router.navigate(['place', { outlets: { popup: null } }]);

Oh then its easy right?

this.router.navigate(['place', 'someId', { outlets: { popup: null } }]);should then navigate me to http://localhost:4200/#/place/someId right?

Wrong. The router generates a non-sensical route for me: "/place/(someId//popup:tabs-modal)"

Am I doing something wrong? Or is it just buggy?


Solution

  • this.router.navigate(['/', 'place', { outlets: { popup: null } }]);
    

    You are required to lead from the root path

    EDIT:

    There is an outstanding issue on angular router hopefully fixed with this pull request: https://github.com/angular/angular/pull/22394

    The issue relating to empty router outlets. You also need to know that relative paths are only relative to the router tree (ActiveRoutes) and not the URL. With that in mind, I've created a helper function to get around the issue until its fixed in Angular 6.

    import { Router, ActivatedRoute } from '@angular/router';
    /**
     *
     * Angular Relative path tempory solution. Angular doesn't like empty paths.
     * Should be fixed in version 6 Pull request 22394
     * https://github.com/angular/angular/pull/22394
     *
     * Angular Issue: https://github.com/angular/angular/issues/13011#issuecomment-274414952
     *
     * Before removing check relative paths work on named outlet. Using Navigate on named
     * outlet currently relates to secondary routes (outlet:'route/test)
     * this meant breaking out wasn't possiable using ../../ like documented in
     * angular own documentation
     *
     * key Information: This is relative to routes like anuglar intended NOT URL path
     *
     * Bug only relates to going to parent and down the tree
     *
     * @export NavigateByRelative
     * @param {string} path
     * @param {Router} router
     * @param {ActivatedRoute} route
     *
     */
    export function NavigateByRelative(path: string, router: Router, route: ActivatedRoute) {
    
        /**
         * Relative paths should always start with '../' as per angular documentation
         * https://angular.io/guide/router#relative-navigation
         */
        if (path.startsWith('../')) {
            // split path into multiple paths
            const paths = path.split('/');
    
            // minus 1 on length as we gurantee need the last index
            const totalPathToLastIndex = paths.length - 1;
    
            // current index so we can start at this later on
            let currentPathIndex;
    
            // Relative to is so we get to the correct parent
            let relativeTo = route;
    
            // Check their is a parent and the current path still intended to go back up the tree
            for (currentPathIndex = 0;
                currentPathIndex < totalPathToLastIndex
                && relativeTo.parent !== undefined
                && paths[currentPathIndex] === '..';
                currentPathIndex++
            ) {
                relativeTo = relativeTo.parent;
            }
    
            // Navigate starting at the the currentpathIndex and relative to the current parent
            router.navigate([...paths.splice(currentPathIndex )], { relativeTo });
    
        } else {
            // else use navigation as normal as this should work correctly
            router.navigate([path]);
        }
    }

    Update: 23/10/2018 Sorry for the delay. As of angular 6 the issue with router navigation has now been resolved

    Update: 02/04/2019 Angular 7+ has introduce the bug again.