angular 2 - 如何在某些组件中隐藏导航栏
Posted
技术标签:
【中文标题】angular 2 - 如何在某些组件中隐藏导航栏【英文标题】:angular 2 - how to hide nav bar in some components 【发布时间】:2017-08-24 10:07:07 【问题描述】:我在 nav.component.html 中单独创建了导航栏,如何在 login.component 等一些组件中隐藏导航栏。
nav.component.html
<nav class="navbar navbar-default navbar-fixed-top navClass">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
(click)="toggleState()">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse"
[ngClass]=" 'in': isIn ">
enter code here <ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">about</a></li>
</ul>
</div>
</div>
</nav>
【问题讨论】:
【参考方案1】:整个应用程序通常需要导航栏控制和格式化,因此 NavbarService 很有用。在你需要的地方注入那些组件。
navbar.service.ts:
import Injectable from '@angular/core';
@Injectable()
export class NavbarService
visible: boolean;
constructor() this.visible = false;
hide() this.visible = false;
show() this.visible = true;
toggle() this.visible = !this.visible;
doSomethingElseUseful()
...
navbar.component.ts:
import Component from '@angular/core';
import NavbarService from './navbar.service';
@Component(
moduleId: module.id,
selector: 'sd-navbar',
templateUrl: 'navbar.component.html'
)
export class NavbarComponent
constructor( public nav: NavbarService )
navbar.component.html:
<nav *ngIf="nav.visible">
...
</nav>
example.component.ts:
import Component, OnInit from '@angular/core';
import NavbarService from './navbar.service';
@Component(
)
export class ExampleComponent implements OnInit
constructor( public nav: NavbarService )
ngOnInit()
this.nav.show();
this.nav.doSomethingElseUseful();
【讨论】:
太好了,很高兴为您提供帮助! 谢谢!我在下面的答案中添加了对此答案的可能扩展。 感谢@Dan 提供简洁的解决方案 毫无疑问,这个解决方案是有效的。但理想情况下,服务应该包含 API 调用和 http 相关的东西,而不是显示/隐藏逻辑! 这仍然适用于 Angular 6 吗?我似乎无法使其工作,如果其他组件的 onInit 将其更改为 true,则 nav 组件上的 nav.visible 仍然显示为 false。【参考方案2】:通过向 route.module 中的路线添加数据对象,我能够在不使用导航/工具栏服务的情况下解决此问题。我扩展了Todd Motto's example of adding dynamic titles to a page 并将toolbar: false/true
添加到我路径中的数据对象中。然后我在toolbar.component 中订阅了路由器事件。使用 Todd 的事件监听函数,我读取路径对象并使用布尔值设置工具栏可见或不可见。
无需服务,可在 pagerefresh 上工作。
路由模块
...
const routes: Routes = [
path: 'welcome', component: WelcomeComponent, data: title: 'welcome', toolbar: false , ...];
工具栏组件
constructor(private router: Router, private activatedRoute: ActivatedRoute, public incallSvc: IncallService)
this.visible = false; // set toolbar visible to false
ngOnInit()
this.router.events
.pipe(
filter(event => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map(route =>
while (route.firstChild)
route = route.firstChild;
return route;
),
)
.pipe(
filter(route => route.outlet === 'primary'),
mergeMap(route => route.data),
)
.subscribe(event =>
this.viewedPage = event.title; // title of page
this.showToolbar(event.toolbar); // show the toolbar?
);
showToolbar(event)
if (event === false)
this.visible = false;
else if (event === true)
this.visible = true;
else
this.visible = this.visible;
工具栏.html
<mat-toolbar color="primary" *ngIf="visible">
<mat-toolbar-row>
<span>viewedPage | titlecase</span>
</mat-toolbar-row>
</mat-toolbar>
【讨论】:
谢谢,这是我在这里看到的最好的方法。 :) 你在用管道、过滤器、合并映射和订阅做什么?看起来您正在检查路线,并可能根据路线设置标题? firstChild 有什么帮助? (对不起,我有点新手) 在我的回答中查看 Motto 示例的链接。它很好地解释了他如何使用 rxjs 运算符(map 等)来获取路由中的数据对象。您需要访问 firstChild 以获取路线数据。花点时间阅读 Motto 的解释并深入了解每个部分,因为该示例使用了 Angular 中所有激活的路由部分的许多有用部分。祝你好运,继续提问! 非常好的答案,在大规模应用中具有巨大的可用性潜力!【参考方案3】:添加到Dan 的答案。
完整答案需要更多细节。它将NavbarService
注册为app.module.ts
的整个应用程序的提供者
import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import FormsModule from '@angular/forms';
import HttpModule from '@angular/http';
import SharedModule from './shared/shared.module';
import AppComponent from './app.component';
import NavbarModule from './navbar/navbar.module';
import NavbarService from './navbar/navbar.service';
import AppRoutingModule, routedComponents from './routing.module';
@NgModule(
imports: [
BrowserModule, FormsModule, HttpModule,
NavbarModule,
SharedModule,
AppRoutingModule
],
declarations: [
routedComponents,
],
providers: [
// Here we register the NavbarService
NavbarService
],
bootstrap: [AppComponent]
)
export class AppModule
【讨论】:
【参考方案4】:我喜欢上面 Dan 的 answer。但是,它确实会产生一些更新控制台错误,这是我不希望在生产应用程序中出现的。我建议改用这种方法:answer。
使用 canDeactivate 来完成实现也可能会有所帮助。在我隐藏导航栏的地方,例如登录时,我添加了一个导航离开“canDeactive”服务:
path: 'login', component: LoginComponent, canDeactivate: [NavigateAwayFromLoginDeactivatorService] ,
停用服务如下所示:
import Injectable from '@angular/core';
import CanDeactivate from '@angular/router';
import LoginComponent from "app/user/login/login.component";
import NavbarTopService from "app/navbar-top/navbar-top.service";
@Injectable()
export class NavigateAwayFromLoginDeactivatorService implements CanDeactivate<LoginComponent>
constructor(public nav: NavbarTopService)
canDeactivate(target: LoginComponent)
this.nav.show();
return true;
这样,我只能在登录时隐藏,而无需在所有其他组件上调用 show()
。
【讨论】:
你的方法很好。通过使用这种方法,我实现了它来隐藏登录组件中的菜单和标题以及主组件中的标题和菜单显示,但问题是当我们再次刷新浏览器窗口时,标题和菜单对主组件隐藏。我没有得到确切的问题是什么。如果可能,请提供帮助。【参考方案5】:您可以在 nav 所在的组件上使用 ngIF 指令
<nav *ngIf="this.currentRoute!=='login'" navigation>
</nav>
获得当前路线后:
this.router.events.subscribe(event =>
if (event.constructor.name === "NavigationEnd")
this.name = (<any>event).url.split("/").slice(-1)[0];
this.isLogin = this.currentRoute === 'login';
)
【讨论】:
【参考方案6】:在模板中添加 *ngIf='!showNav'
<nav class="navbar navbar-default navbar-fixed-top navClass" *ngIf='!showNav' >
在登录组件中
showNav = true;
这将显示所有页面的导航其余部分,如果您想隐藏在任何页面中,只需在该组件中输入showNav = true;
。
工作原理:
首先它会检查 showNav
变量,但它不可用,因此对于我们要显示菜单的其他页面,它将返回 false,因此需要在任何其他页面中声明该变量。
在登录页面中,我们将值设置为true,因此它将使其为false并隐藏导航。
【讨论】:
我已经在我的项目中进行了测试,效果很好,你有什么错误吗? 我不明白你为什么否定那个布尔值... showNav = false 会更容易理解... 如果您想在 DOM 中简单地没有导航 HTML,则此方法有效,但不幸的是,组件仍将被初始化,这可能是不可取的。 这不起作用,如果你有你的导航栏在一个自己的组件中。因为 NavbarComponent 不知道 LoginComponent 的实现。【参考方案7】:为了让它工作,还要在导入 NavbarService 的任何地方添加“提供者”
navbar.component.ts 和 example.component.ts
@Component(
moduleId: module.id,
selector: 'sd-navbar',
templateUrl: 'navbar.component.html',
providers: [NavbarService ]
)
【讨论】:
【参考方案8】:此问题的另一个解决方案,特别是如果您希望从其他控件打开/关闭/切换/侧导航栏,是在服务中保存对侧导航栏的引用,如下所述:
https://***.com/a/48076331/1013544
这对我来说效果很好,因为我有一个应用程序,其中侧导航更像根元素,路由器组件是它的内容,因此当侧导航菜单打开时它们将在后台被禁用。
【讨论】:
【参考方案9】:如果您要隐藏 mat-sidenav 元素,JaganY 的 linked answer above 是最佳答案。您永远不应该让像这样的简单代码需要更改检测。以下是其他类型元素的示例:
app.componenent.html
<nav #rNav>
<app-rightnav></app-rightnav>
</nav>
app.componenent.ts
@ViewChild('rNav') rNav!: ElementRef;
constructor(public nav: NavbarService)
ngAfterViewInit(): void
this.nav.setRight(this.rNav);
navbar.service.ts
import Injectable, ElementRef from '@angular/core';
@Injectable(
providedIn: 'root'
)
export class NavbarService
private right!: ElementRef;
private visible!: boolean;
hideR()
this.visible = false;
this.right.nativeElement.style.display = 'none';
showR()
this.visible = true;
this.right.nativeElement.style.display = 'block';
toggleR() this.visible ? this.hideR() : this.showR();
setRight(e: ElementRef)
this.right = e;
child-components.html
constructor()
this.nav.hideR(); // or this.nav.showR();
【讨论】:
以上是关于angular 2 - 如何在某些组件中隐藏导航栏的主要内容,如果未能解决你的问题,请参考以下文章
Angular 8. 如何在登录页面单击登录按钮,并在下一页的导航栏组件上显示用户名?
如何在使用页面锚导航时将“激活”类设置为 Angular 2 中的引导导航栏?