【问题标题】:angular 2 - how to hide nav bar in some componentsangular 2 - 如何在某些组件中隐藏导航栏
【发布时间】: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>

【问题讨论】:

    标签: html angular


    【解决方案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://stackoverflow.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();
            }
            

            【讨论】:

              猜你喜欢
              • 2019-04-05
              • 1970-01-01
              • 1970-01-01
              • 2021-01-29
              • 2020-08-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多