首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角路由器链路主动嵌套菜单

角路由器链路主动嵌套菜单
EN

Stack Overflow用户
提问于 2018-11-14 12:11:46
回答 4查看 10.5K关注 0票数 4

我试着做一个有角度路径的嵌套菜单。

我需要的是将类应用到嵌套路由(如果它是活动的),并将类应用到父组件(如果其子组件是活动的)。

我怎样才能做到这一点?现在,我正在进行递归菜单构建,以便在需要多级嵌套时使用方便。

component.html

代码语言:javascript
复制
<a (click)="toggleActive()" [class.active]="isActive" [routerLink]="menuItem.link" *ngIf="menuItem.link; else noLink">
  <i *ngIf="menuItem.faClass" class="fa fa-{{menuItem.faClass}}"></i>
  {{menuItem.name}} <span *ngIf="menuItem.children && menuItem.children.length > 0" class="fa fa-chevron-down"></span>
</a>

<ng-container *ngIf="menuItem.children && menuItem.children.length > 0">
  <ul class="nav child_menu" [class.active]="isActive" routerLinkActive="active"
      *ngFor="let item of menuItem.children">
    <li menu-item [menuItem]="item" (checkActive)="updateActiveState()"></li>
  </ul>
</ng-container>

<ng-template #noLink>
  <a (click)="toggleActive()" [class.active]="isActive">
    <i *ngIf="menuItem.faClass" class="fa fa-{{menuItem.faClass}}"></i>
    {{menuItem.name}} <span *ngIf="menuItem.children && menuItem.children.length > 0" class="fa fa-chevron-down"></span>
  </a>
</ng-template>

component.ts

代码语言:javascript
复制
@Component({
  selector: '[menu-item]',
  templateUrl: './menu-item.component.html',
  styleUrls: ['./menu-item.component.scss'],
  host: {
    '[class.active]': 'hostActive && isActive',
    '[class.active-sm]': 'hostActiveSm && isActive'
  }
})
export class MenuItemComponent implements OnInit, AfterViewInit, OnChanges {

  public menuSize;
  public isActive = false;

  @Input() menuItem: MenuItem;
  @Output() checkActive: EventEmitter<void> = new EventEmitter<void>();
  @ViewChild(MenuItemComponent) menuComponent: MenuItemComponent;

  private hostActive = true;
  private hostActiveSm = false;

  @HostBinding('class') hostClass = this.hostActive && this.isActive ? 'active' : this.hostActiveSm && this.isActive ? 'active-sm' : '';

  constructor(
    private router: Router,
    private uss: UiStateService,
  ) {
  }

  ngOnInit() {
    this.uss.menuSubject.subscribe(msg => {
      this.menuSize = msg;
      if (this.menuSize === MenuSizes.sm) {
        this.hostActive = false;
        this.hostActiveSm = true;
      } else {
        this.hostActive = true;
        this.hostActiveSm = false;
      }
      this.updateActiveState();
    });

    this.router.events.subscribe((e: Event) => {
      if (e instanceof NavigationEnd) {
        this.updateActiveState();
      }
    });
  }

  ngOnChanges() {
  }

  ngAfterViewInit() {
    this.updateActiveState();
  }

  public toggleActive(): void {
    this.isActive = !this.isActive;
    // if (this.menuComponent) {
    //   this.menuComponent.isActive = true;
    // }
  }

  private updateActiveState(): void {
    // reset previous state
    this.isActive = false;
    if (this.menuComponent) {
      this.menuComponent.isActive = false;
    }

    // Check state of item with no els
    const url = this.router.url;
    console.log('URL', url, 'Menu link', this.menuItem.link);
    console.log(url.match('/' + this.menuItem.link + '$/'));
    if (this.menuItem && this.menuItem.link && url.match('/' + this.menuItem.link + '$/')) {
      this.isActive = true;
      this.checkActive.emit();
    }

    if (this.menuComponent) {
      console.log('Menu component');
      console.log(this.menuComponent, this.menuComponent.menuItem.link);
      this.isActive = true;
    }
  }

}

是否有方法从组件中知道它的路由是否是活动的?诀窍是,我使用的是[routerLink],而不是routerLink,这样我就可以将.作为根页面的链接传递。

更新

尽我所能再现stackblitz,试着访问"Dasboard“。它应该向父li添加一个“活动”类。如果您自己添加它,您将看到它的元素上的应用类和右边的一个有色条。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-11-25 14:57:12

我设法解决了这个问题。StackBlitz

主要是通过在setTimeOut事件中没有时间地使用navigateEnd来实现的,这样我就可以检查isActive的状态并获得值(如果没有setTimeout,则值是“从过去”得到的,意思是在取值时没有更新)。它的工作方式有点棘手,但却很有效。

票数 0
EN

Stack Overflow用户

发布于 2018-11-19 09:22:21

也许您可以尝试在任何组件中访问ActivatedRoute。

代码语言:javascript
复制
import { Router, ActivatedRoute} from '@angular/router';    

 constructor(private router: Router, private activatedRoute:ActivatedRoute) {
    console.log(activatedRoute.snapshot.url)  // array of states
    console.log(activatedRoute.snapshot.url[0].path) 
 }

希望这会有帮助!

票数 0
EN

Stack Overflow用户

发布于 2018-11-21 18:52:07

StackBlitz

所有这些功能都是内置在角的路由器模块中的。这就是儿童路线背后的全部想法。如果一个路由是真正的父组件,那么它应该是路由中的父组件。通过这样做,您可以简单地检查父路由是否是活动的,而不是应用程序组件中任意分配的任何路由。

此外,这有一个巨大的好处,就是允许仪表板简单地路由到['../sibling']

在我的子路由(特别是/home/home. that )中,您将看到一个注释行,它将使仪表板能够自动加载(如果这是所需的行为)。

您已经在动态菜单项中使用了routerLinkActive,但是要有最直接的方法,它应该在绑定到routerLink的项上,如概述的这里

您可能会遇到的最大问题是,嵌套的routerLink元素并不像这个问题中讨论的那样很好地在DOM中发挥作用,因此您需要停止传播。

app-component.html

代码语言:javascript
复制
<ul app-menu-item 
  class="nav side-menu"
  [menu]="menu">
</ul>

菜单-item.html:

代码语言:javascript
复制
<li
  *ngFor="let item of menu"
  [routerLink]="item.link"
  routerLinkActive="active"
  (click)="stop($event)">

    {{item.name}}

    <ul app-menu-item
      *ngIf="item.children"
      class="nav side-menu"
      [menu]="item.children">
    </ul>
</li>

虽然它没有回答问题中的标题,但我将补充说,这个问题最容易通过使用父路由来解决,然后按如下方式设置menu-item.html:

代码语言:javascript
复制
<li *ngFor="let item of menu">
  <a [routerLink]="item.link" routerLinkActive="active">
    {{item.name}}
  </a>
  <ul class="nav side-menu"
  *ngIf="item.children"
  app-menu-item [menu]="item.children">
  </ul>
</li>

然后使用scss中的同级选择器显示或隐藏菜单。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53299952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档