从路由器插座导航到父路径(NG5)

时间:2017-11-13 17:21:59

标签: angular angular-router

问题

尝试从http://localhost:4200/#/place/(popup:tabs-modal)导航 (插座)http://localhost:4200/#/place/someId

请注意,该商店基本上是通往"地点"的儿童路线。

我能做什么

我可以关闭插座,然后结束:http://localhost:4200/#/placethis.router.navigate(['place', { outlets: { popup: null } }]);

那么它很容易吗?

this.router.navigate(['place', 'someId', { outlets: { popup: null } }]);然后应该导航到http://localhost:4200/#/place/someId对吗?

错误。路由器为我生成一条非感性路线:"/place/(someId//popup:tabs-modal)"

我做错了吗?还是只是马车?

4 个答案:

答案 0 :(得分:2)

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

您需要从根路径

领导

编辑:

角度路由器有一个突出的问题,希望通过此拉取请求修复:https://github.com/angular/angular/pull/22394

与空路由器插座有关的问题。您还需要知道相对路径仅相对于路由器树(ActiveRoutes)而不是URL。考虑到这一点,我创建了一个辅助函数来解决问题,直到它在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]);
    }
}

更新:23/10/2018 抱歉耽搁了。从角度6开始,路由器导航问题现已解决

更新:02/04/2019 Angular 7+再次引入了这个bug。

答案 1 :(得分:1)

我放弃了尝试让.navigate()工作,最后使用了router.navigateByUrl('/place/someId')。一个简单的解决方案让我望而却步。

答案 2 :(得分:0)

可接受的答案是一种不好的做法,因为您肯定不想在要关闭弹出窗口或任何其他操作时浏览NavigationByUrl。最好的办法是在路由器中执行以下操作:

{
        path: 'place/:someid',
        component: PlacePageComponent,
        resolve: {someid: SomeIDResolver},
        children: [
            {
                path: 'tabs-modal/:maybenextidhere',
                outlet: 'popup',
                component: TabsModalComponent,
                resolve: {maybenextidhere: MaybeNextIDResolver},
            },
        ]
    },

然后是诀窍。在您要关闭弹出窗口的函数中,您想要调用如下代码:

this.router.navigate(['./', {outlets: { popup: null}}], {relativeTo: this.route.firstChild.firstChild});

答案 3 :(得分:0)

我遇到了同样的问题。问题是我希望能够在任何深度使用我的组件。因此,https://stackoverflow.com/a/50976238/1617590解决方案使我创建了一种稍微不同且更灵活的方法。

Helper方法将遍历主ActivatedRoute并返回ActivatedRoute属性所需的relativeTo,以正确地导航到辅助出口。

private getRelativeTo(
  obj: ActivatedRoute,
  callback: (lastFirstChild: ActivatedRoute) => void
) {
  Object.keys(obj).forEach((key) => {
    if (key === 'outlet') {
      if (obj[key] === PRIMARY_OUTLET) {
        const fChild = obj.firstChild;
        const nextFChild = fChild ? fChild!.firstChild : undefined;
        if (fChild && nextFChild) {
          nextFChild.outlet === 'modal' // name of your secondary outlet
            ? callback(fChild) // found child component with named outlet
            : this.getRelativeTo(fChild, callback) // not found, go deeper
        } else {
          // No named child outlet found so just return back.
          callback(this.route);
        }
      } else {
        // First child is not the primary, so just return back.
        callback(this.route);
      }
    }
  });
}

这就是我用来关闭模态的方法:


...

constructor(
  private router: Router,
  private route: ActivatedRoute
) {}

closeModal() {
  this.getRelativeTo(this.route, (lastFirstChild) => {
    this.router.navigate(['./', { outlets: { modal: null } }], {
      replaceUrl: true,
      relativeTo: lastFirstChild,
    });
  });
}

这种方法可帮助我在与主插座相同的级别上以及用作子组件时,正确地从带有命名辅助插座的子路线中导航出来。

希望有帮助。

相关问题