首页 文章

Angular 2 Activatedroute参数不在服务中或在<router-outlet>外部工作

提问于
浏览
17

我有一个非常奇怪的问题:index.html

<navigation-menu *ngIf="isLoggedIn"></navigation-menu>
<div class="content-wrapper" [ngClass]="{'fullContent' : !isLoggedIn}">
    <section class="content">
        <router-outlet></router-outlet>            
    </section>
</div>

导航菜单是导航菜单的组件 . 在路由器插座内容中有一个名为“资产”的组件 .

我在资产组件中做了什么:

import { ActivatedRoute}from "@angular/router";
constructor(private route: ActivatedRoute){}
public ngOnInit(): void {
    this.route.params.subscribe(params => {
        const id = params["id"];
}

这有效,我得到了我的路线参数(这是一种“资产/:id”) .

现在我在导航菜单组件(在路由器出口“之外”)和名为contextservice的全局服务中尝试了相同的操作 . 与上面的代码相同,但在路由更改时甚至没有触发 . 如果我尝试获取当前路由器快照

const strId = this.route.snapshot.params["id"];

在触发NavigationEnd事件之后,结果是相同的:strId是未定义的,因为params是一个空对象 .

它只适用于我的资产组件 . 这是按预期工作还是应该如何处理?

我的意图是从全局服务(或导航菜单中的“全局”组件)触发事件,该事件正在监听所有路径(-params)更改 .

我唯一的解决方案是在每个NavigationEnd事件之后解析完整的URL,在我看来这是不正确的方式......或者处理每个子组件(在路由器插座中)的params更改 .

也许我在理解中只有一个基本错误......

谢谢

接受答案的解决方案:

this.router.events.subscribe(val => {
        if (val instanceof RoutesRecognized) {
            var strId = val.state.root.firstChild.params["id"];
        }});

不要忘记从角度路由器导入RoutesRecognized !!

3 回答

  • 17

    路由器添加的组件获取路由器段( ActivatedRoute ),但在服务中没有激活路由 . 您可以订阅router.events并遍历路由树(router.firstChild ...`)以获取您需要的特定路由分段的参数 .

    另见https://github.com/angular/angular/issues/11023

  • 0

    这是一个有角度的服务,它可以做到:

    import {Injectable}                                                        from '@angular/core';
    import {ActivatedRoute, NavigationEnd, NavigationExtras, ParamMap, Router} from "@angular/router";
    import {RouterExtensions}                                                  from "nativescript-angular/router";
    import {NavigationOptions}                                                 from "nativescript-angular/router/ns-location-strategy";
    import {Observable}                                                        from "rxjs/Observable";
    import {first}                                                             from "rxjs/operators/first";
    import {filter}                                                            from "rxjs/operators/filter";
    import {map}                                                               from "rxjs/operators/map";
    import {switchMap}                                                         from "rxjs/operators/switchMap";
    import {unRegisterAndroidOnBack}                                           from "../../utils/view.utils";
    
    @Injectable()
    export class RoutingService
        {
            constructor(private routerExtensions: RouterExtensions, private route: ActivatedRoute, private router: Router)
            {
            }
            public getActivatedRouteParameter(paramName: string): Observable<ParamMap>
            {
                return this.router.events.pipe(filter(e => e instanceof NavigationEnd),
                                               map((): ActivatedRoute =>
                                                   {
                                                       let route = this.route;
                                                       while (route.firstChild)
                                                           {
                                                               route = route.firstChild;
                                                           }
                                                       return route;
                                                   }),
                                               filter((route: ActivatedRoute) => route.outlet === 'primary'),
                                               switchMap((route: ActivatedRoute) => route.paramMap) , first());
    
            }
    

    .

  • 1

    实际上,您的activatedRoute是正确的并且已更新,但您拥有所有树 . 所以如果你一直走在route.firstChild里面,你最终会找到最后一条路线,我称之为deepActivatedRoute(在route.firstChild里面...... route.firstChild)

    所以我所做的是创建一个服务来跟踪deepRoute,并让它始终可访问

    import { Injectable } from '@angular/core';
    import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
    
    @Injectable()
    export class ActivatedRouteService {
      private _deeperActivatedRoute: ActivatedRoute;
      get deeperActivatedRoute(): ActivatedRoute {
        return this._deeperActivatedRoute;
      }
    
      constructor(private router: Router, private route: ActivatedRoute) {}
    
      init(): void {
        this.router.events.subscribe(event => {
          if (event instanceof NavigationEnd) {
            // Traverse the active route tree
            let activatedChild = this.route.firstChild;
            if (activatedChild != null) {
              let nextActivatedChild;
              while (nextActivatedChild != null) {
                nextActivatedChild = activatedChild.firstChild;
                if (nextActivatedChild != null) {
                  activatedChild = activatedChild.firstChild;
                }
              }
            }
    
            this._deeperActivatedRoute = activatedChild || this.route;
          }
        });
      }
    }
    

    然后在app.component.ts中我启动服务(只是为了确保它始终跟踪)

    export class AppComponent {
      constructor(private activatedRouteService: ActivatedRouteService) {
        this.activatedRouteService.init();
      }
    }
    

    最后,无论您身在何处,都可以选择自己的路线:

    export class ForbiddenInterceptor implements HttpInterceptor {
      constructor(private activatedRouteService: ActivatedRouteService) { }
    
      doYourStuff(): void {
           //you'll have the correct activatedRoute here
           this.activatedRouteService.deeperActivatedRoute;
      }
    }
    

    回答这个问题,您可以采取更深入的激活路径并正常检查snapshop.url,就像在组件中一样

相关问题