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:获取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
相关产品推荐
相关产品推荐

