我有一个简单的TopbarComponent
,它基本上在我的 View 顶部添加了一个引导导航栏。
由于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
}
])
其模板如下所示:
<my-topbar></my-topbar>
<div class="container-fluid">
<div class="row">
<router-outlet></router-outlet>
</div>
</div>
现在,我想使用
ngIf
(或使用CSS将其隐藏以外的任何其他方式)来隐藏多条路线上的顶部栏,例如/login
。我尝试了几种使用
@CanAcitvate()
或在自己的OnActivate
中实现LoginComponent
的方法(以及从AppComponent
中尝试它的方法),但是没有任何效果(甚至无法启动函数也有问题)。我最近得到的是在
Router
中直接使用AppComponent
,如下所示:export class AppComponent implements OnInit{
showTopbar:boolean;
constructor(private _router:Router) {}
ngOnInit():any {
this.showTopbar = this._router.lastNavigationAttempt != '/login';
}
}
在我的
app.component.html
中,我将指令更改为<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;
}
};
太糟糕了,我无法以这种方式在
data
中使用@RouteConfig
属性。感觉会更好。 最佳答案
我已经将类似问题困扰了一段时间。
起初,我发现的解决方案似乎有些棘手,但将来可以为我解决许多类似的问题。
基本上,您必须使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);
}
}
这是自定义路由器导出的非常基本的实现。您的逻辑必须在Activate方法中实现,每次更改路径时都要调用该方法。
通过这种方法,您可以检查 route 的data属性。
主要的问题是,指令现在无法发出事件...它们仅接受输入,不能触发任何输出...
我找到了解决此问题的方法:使用
EventEmitter
创建一个服务以在组件和指令之间进行通信:@Injectable()
export class PubsubService {
private _pubSubber: EventEmitter<any> = new EventEmitter();
routeisChanging(obj:any) {
this._pubSubber.emit(obj);
}
onRouteChanged() {
return this._pubSubber;
}
}
AppComponent订阅
onRouteChanged
事件:subscription:any;
constructor(private _pubsubService:PubsubService) {
this.subscription = this._pubsubService.onRouteChanged().subscribe(data => {
/**YOUR CUSTOM LOGIC HERE*/});
}
需要时,CustomRouterOutlet会在
activate
方法中触发事件:activate(nextInstruction: ComponentInstruction): Promise<any> {
//***YOUR CUSTOM LOGIC HERE***
this._pubsubService.routeisChanging(nextInstruction.routeData.data['hideTopbar']);
return super.activate(nextInstruction);
}
这样,您可以使用任何逻辑轻松实现路由器与
AppComponent
之间的通信。您必须记住将通信服务注入(inject)应用程序的
RootComponent
中。