如何在Angular2中操作特定路径上的组件

lex*_*ith 9 angular2-routing angular

我有一个简单的TopbarComponent,它基本上在我的视图顶部添加了一个bootstrapish导航栏.

由于90%的模板都应该包含此指令,我想通过我的处理它app.component看起来像这样:

import ...;

@Component({
    selector: 'my-app',
    templateUrl: 'app/app.component.html',
    directives: [ROUTER_DIRECTIVES, TopbarComponent, ...],
    providers: [ROUTER_PROVIDERS, ...]
})

@RouteConfig([
{
    path: '/login',
    name: 'Login',
    component: LoginComponent
},
{
    path: '/dashboard',
    name: 'Dashboard',
    component: DashboardComponent,
    useAsDefault: true
}
])
Run Code Online (Sandbox Code Playgroud)

其模板看起来像这样:

<my-topbar></my-topbar>

<div class="container-fluid">
    <div class="row">
        <router-outlet></router-outlet>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

现在我想使用ngIf(或除了用css隐藏它之外的任何其他方式)来隐藏几条路线上的顶杆,/login例如.我尝试了几种方法在我的使用@CanAcitvate()或实现(以及从我的尝试),但没有任何影响(甚至有问题甚至让功能开火).我得到的最接近的是直接使用我喜欢的:OnActivateLoginComponentAppComponentRouterAppComponent

export class AppComponent implements OnInit{
    showTopbar:boolean;

    constructor(private _router:Router) {}

    ngOnInit():any {
        this.showTopbar = this._router.lastNavigationAttempt != '/login';
    }
}
Run Code Online (Sandbox Code Playgroud)

并在我的app.component.htmli中将指令更改为<my-topbar *ngIf="showTopbar"></my-topbar>

但这只适用于我的应用程序的初始加载,因为ngOnInit每次状态更改都不会触发原因.有没有类似的方法我可以使用(并且找不到)或者我在这里走向错误的方向?


编辑:

目前,PierreDuc的答案对我不起作用,但我尝试了类似的方法,使用location.path()如下:

constructor(private _location:Location) {}

private get _hideTopbar() : boolean {
    switch(this._location.path()){
        case '/register':
        case '/login':
            return true;
        default:
            return false;
    }
};
Run Code Online (Sandbox Code Playgroud)

太糟糕了,我不能在这种方法中使用该data属性@RouteConfig.感觉会好一些.

Mat*_*osi 5

我已经在一段时间内遇到了类似的问题.我发现的解决方案起初可能会被视为棘手,但可以在将来为我解决此类问题.

基本上,您必须router-outlet在路由更改时发出一个事件,让您AppComponent收听该自定义事件.

第一步是创建自定义路由器插座:

@Directive({
selector: 'custom-router-outlet'
})
export class CustomRouterOutlet extends RouterOutlet {
    private parentRouter:Router;

    constructor(_elementRef: ElementRef,
            _loader: DynamicComponentLoader,
            _parentRouter: Router,
            @Attribute('name') nameAttr: string) {
    super(_elementRef, _loader, _parentRouter, nameAttr);
    this.parentRouter = _parentRouter;
    }

    activate(nextInstruction: ComponentInstruction): Promise<any> {
        //***YOUR CUSTOM LOGIC HERE***
        return super.activate(nextInstruction);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是自定义路由器插座的一个非常基本的实现.您的逻辑必须在activate方法中实现,在每次路由更改时调用.在此方法中,您可以检查路径中的数据属性.

主要问题是,目前,指令不能发出事件......它们只接受输入,不能触发任何输出......

我找到了解决此问题的方法:使用以下方法为组件和指令之间的通信创建服务EventEmitter:

@Injectable()
export class PubsubService {
    private _pubSubber: EventEmitter<any> = new EventEmitter();

    routeisChanging(obj:any) {
        this._pubSubber.emit(obj);
    }

    onRouteChanged() {
        return this._pubSubber;
    }
}
Run Code Online (Sandbox Code Playgroud)

AppComponent订阅的onRouteChanged事件:

subscription:any;
constructor(private _pubsubService:PubsubService) {
    this.subscription = this._pubsubService.onRouteChanged().subscribe(data => {
        /**YOUR CUSTOM LOGIC HERE*/});
}
Run Code Online (Sandbox Code Playgroud)

CustomRouterOutlet触发的事件activate需要时方法:

activate(nextInstruction: ComponentInstruction): Promise<any> {
    //***YOUR CUSTOM LOGIC HERE***
    this._pubsubService.routeisChanging(nextInstruction.routeData.data['hideTopbar']);
    return super.activate(nextInstruction);
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以轻松地实现路由器AppComponent与任何逻辑之间的通信.

您必须记住在RootComponent您的应用程序中注入通信服务.