Edited at

AngularのRouterで遷移したとき、パラメータ解釈前のパス文字列をゲットする

More than 1 year has passed since last update.


やりたいこと


/something-page/1


にアクセスしたとき、RouterModule.forRoot等で定義した


/something-page/:id


みたいな文字列がほしい。


やりかた


  • Routerのイベントをsubscribeします。

  • イベントのステートによるフィルタは任意ですが、RouteRecognizedより前のNavigationStartでは、RouterEvent.state.rootundefinedなのでアウトです。


  • ActivatedRouteSnapshot::childrenが、RouterModule.forRootに渡したRoutesorRoute[]の階層を、逆にたどるような感じになっているので、childrenを再帰的にたどります。

  • 各階層のActivatedrouteSnapshotがもっているrouteConfigpathに、パラメータ変換前のパス(:idみたいなの)が入っているので、これを抽出すればOKです。

  • 一番上階層のActivatedRouteSnapshot=RouterEvent.state.rootは、なぜかrouteConfigがundefinedなので、ちゃんと識別するようにしましょう(return時に三項演算子かけて、routeConfigの存在をチェックしてます)。

export class GetPathService {

constructor(private router: Router) {
router.events
.pipe(filter(e => e instanceof RoutesRecognized))
.subscribe((e: RoutesRecognized) => {
console.log(getPath(e.state.root));
});
}
}

function getPath(node: ActivatedRouteSnapshot) {
const c =
node.children.length > 0 ? `/${getPath(node.children[0])}` : '';
return `${node.routeConfig ? node.routeConfig.path : ''}${c}`;
}


結果について

先ほど


ActivatedRouteSnapshot::childrenが、RouterModule.forRootに渡したRoutesorRoute[]の階層と同じ階層構造になっている


といった通り、この作りに依存してきます。

たとえば、Routes

[

{
path: '',
children: [
{
path: 'id0001',
children: foo,
},
{
path: 'id0002',
children: bar,
},
]
},
]

のように、間にpath: ''みたいなのが存在すると、その分も階層化されます。

なので、このRoutesを指定した場合の、先ほどのサンプルコードの結果は

//id0001/...

のように、先頭に接続文字列が連続するようになります。


参考

https://github.com/angular/angular/blob/5.0.x/packages/router/src/router_state.ts#L354