You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ngx-bootstrap navbar动态展开异常:登录状态切换后无法正常折叠

ngx-bootstrap Navbar 动态折叠异常问题及解决方案

我在使用ngx-bootstrap navbar时遇到两个关联问题,导航栏通过<ng-container>区分登录/未登录状态,展示不同导航项,实现参考官方示例。

问题详情

问题1:未登录状态小屏不触发折叠

未登录时导航项数量少,屏幕缩小后不会自动折叠为汉堡菜单,仅显示窄版导航栏:

  • 未登录全屏导航栏:全屏
  • 未登录小屏导航栏:小屏

问题2:小屏登录后新增导航项不触发折叠

小屏状态下完成登录,新增的大量导航项不会触发折叠逻辑,导航栏变窄甚至溢出屏幕:

  • 小屏登录后导航栏:小屏登录后

其他正常场景

  • 登录后再缩小屏幕,导航栏可正常折叠为汉堡菜单;
  • 小屏页面加载时已处于登录状态(硬编码测试),导航栏可正常折叠;
  • 小屏状态下登出,导航栏保持折叠状态(这是我期望未登录时也能达到的效果)。

相关代码

模板代码

<nav ngxNavbarDynamicExpand class="navbar navbar-expand-lg">
    <button class="navbar-toggler" type="button" (click)="collapse.toggle()">
      <span><fa-icon [icon]="hamburger"></fa-icon></span>
    </button>
    <div class="container-fluid">
      <ngx-navbar-collapse #collapse="ngxNavbarCollapse">
      <a class="navbar-brand abs" href="https://example.com/">
        <img width=auto
             height="30px"
             src="example.png"
             alt=""
             loading="lazy"sizes="(max-width: 1595px) 100vw, 1595px">
      </a>
      <ul class="navbar-nav me-auto mb-2 mb-md-0">
        <li class="nav-item">
          <a class="nav-link" routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" routerLink="/about" routerLinkActive="active">About</a>
        </li>
      </ul>
      <ng-container *ngIf="(accountService.loggedIn$ | async); else notLoggedIn">
        <div class="dropdown" dropdown>
            <button class="dropdown-toggle text-light transparent-button ml-2" dropdownToggle>Admin</button>
            <div class="dropdown-menu mt-3" *dropdownMenu>
              <a routerLink="/" class="dropdown-item">1</a>
            </div>
        </div>
        <div class="dropdown" dropdown>
            <button class="dropdown-toggle text-light transparent-button ml-2" dropdownToggle>Manage</button>
            <div class="dropdown-menu mt-3" *dropdownMenu>
              <a routerLink="/userdetails" class="dropdown-item">My details</a>
            </div>
        </div>
        <ul class="navbar-nav">
          <li class="nav-item">
              <a class="nav-link" routerLink="/install" routerLinkActive="active">Install</a>
          </li>
          <li class="nav-item">
            <button class="btn btn-primary"
                    routerLink="/"
                    (click)="logout()"
                    role="button">
                    <span class="d-none d-md-inline">Logout</span>
                    <fa-icon [icon]="faPowerOff" [classes]="['ml-md-2']"></fa-icon>
            </button>
          </li>
        </ul>
      </ng-container>
      <ng-template #notLoggedIn>
          <ul class="navbar-nav">
            <li class="nav-item">
              <button class="btn btn-primary"
                      routerLink="/login"
                      role="button">
                      <span class="d-none d-md-inline">Login/Register</span>
                      <fa-icon [icon]="faUser" [classes]="['ml-md-2']"></fa-icon>
              </button>
            </li>
          </ul>
      </ng-template>
    </ngx-navbar-collapse>
  </div>
</nav>

TypeScript代码

import { Component, OnInit } from '@angular/core';
import { faPowerOff, IconDefinition, faBars, faUser } from '@fortawesome/free-solid-svg-icons';
import { AccountService } from '../services/account.service';

@Component({
  selector: 'app-nav',
  templateUrl: './nav.component.html',
  styleUrls: ['./nav.component.css']
})
export class NavComponent implements OnInit {
  faPowerOff: IconDefinition = faPowerOff;
  hamburger: IconDefinition = faBars;
  faUser: IconDefinition = faUser;
  constructor(public accountService : AccountService) { }

  ngOnInit(): void {
  }

  logout(){
    this.accountService.logout();
  }
}

问题原因

ngx-bootstrap的ngxNavbarDynamicExpand指令仅在组件初始化时计算导航栏宽度,判断是否需要折叠。当登录/登出导致导航项动态变化时,指令不会自动重新计算宽度,因此出现折叠逻辑失效的情况:

  1. 未登录时初始宽度足够,小屏状态下不会触发折叠;
  2. 小屏登录后新增导航项,指令未重新检测宽度,无法触发自动折叠。

解决方案

在登录状态变化时,手动触发导航栏的宽度重新计算逻辑:

步骤1:获取Navbar指令实例

通过ViewChild获取NgxNavbarDynamicExpandDirective实例:

import { ViewChild, OnInit } from '@angular/core';
import { NgxNavbarDynamicExpandDirective } from 'ngx-bootstrap-navbar';

// ...

export class NavComponent implements OnInit {
  @ViewChild(NgxNavbarDynamicExpandDirective) navbarDirective!: NgxNavbarDynamicExpandDirective;

  // ...
}

步骤2:监听登录状态变化并触发重新计算

在ngOnInit中订阅登录状态的Observable,状态变化时调用指令的重新计算方法(延迟执行确保DOM已更新):

ngOnInit(): void {
  this.accountService.loggedIn$.subscribe(() => {
    setTimeout(() => {
      this.navbarDirective?.checkExpand();
    }, 0);
  });
}

可选:强制未登录小屏折叠

如果希望未登录状态下小屏也强制折叠,可修改导航栏的响应式类,将navbar-expand-lg改为navbar-expand(默认折叠,仅大屏展开);或添加CSS强制小屏显示汉堡菜单:

@media (max-width: 991.98px) {
  .navbar-expand-lg .navbar-toggler {
    display: block;
  }
  .navbar-expand-lg .ngx-navbar-collapse {
    display: none;
  }
  .navbar-expand-lg .ngx-navbar-collapse.show {
    display: block;
  }
}

内容的提问来源于stack exchange,提问作者WhatsThePoint

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 23:35:18