【问题标题】:Accordion menu with mat-list-item is not working带有 mat-list-item 的手风琴菜单不起作用
【发布时间】:2020-08-09 14:24:00
【问题描述】:

我正在开发一个包含许多模块和子模块的 Angular 9 网络。问题是我需要使用手风琴结构来实现一个包含模块和子项的菜单。另外我正在使用材料设计,我需要使用mat-nav-listmat-list-itema 来实现此功能(我不是在寻找 mat-expansion-panel、ul、li 的解决方案,我需要一个 scss 解决方案对于 mat-list-item)

这是一个示例模板 --> https://primer.fusepx.com/angular/

而这张图片正是我想要做的

我获得了 Angular 4 模板的先前版本,我尝试将样式调整到我的新应用程序,但出现问题并且样式不起作用。这是我得到的结果:

这方面的 scss 非常大,无法使用 stackblitz 进行演示,因为很多事情都不起作用

但基本上我使用 3 个不同的指令将 .open 类放在菜单链接中,我想知道是否还有另一种更简单的方法可以使用 mat-nav-list、mat-list-item 和指令

指令

手风琴指令

import { Directive, OnInit, AfterViewInit, AfterContentChecked } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import 'rxjs/operators';

import { AccordionLinkDirective } from './accordionlink.directive';
import { filter } from 'rxjs/operators';

@Directive({
  selector: '[appAccordion]',
})
export class AccordionDirective implements AfterContentChecked {

protected navlinks: Array<AccordionLinkDirective> = [];

closeOtherLinks(openLink: AccordionLinkDirective): void {
  this.navlinks.forEach((link: AccordionLinkDirective) => {
    if (link !== openLink) {
      link.open = false;
    }
  });
}

addLink(link: AccordionLinkDirective): void {
  this.navlinks.push(link);
}

removeGroup(link: AccordionLinkDirective): void {
  const index = this.navlinks.indexOf(link);
  if (index !== -1) {
    this.navlinks.splice(index, 1);
  }
}

checkOpenLinks() {
  this.navlinks.forEach((link: AccordionLinkDirective) => {
    if (link.group) {
      const routeUrl = this.router.url;
      const currentUrl = routeUrl.split('/');
      if (currentUrl.indexOf( link.group ) > 0) {
        link.open = true;
        this.closeOtherLinks(link);
      }
    }
  });
}

ngAfterContentChecked(): void {
  this.router.events.pipe(
    filter(event => event instanceof NavigationEnd)
  ).subscribe(e => this.checkOpenLinks());
  // this.router.events.filter(event => event instanceof NavigationEnd).subscribe(e => this.checkOpenLinks());
}

constructor( private router: Router) {
  setTimeout(() => this.checkOpenLinks());
}
}

手风琴链接指令

import { Directive, HostBinding, Inject, Input, OnInit, OnDestroy } from '@angular/core';
import { AccordionDirective } from './accordion.directive';

@Directive({
  selector: '[appAccordionLink]'
})
export class AccordionLinkDirective implements OnInit, OnDestroy {

  @Input() public group: any;

  @HostBinding('class.open')
  @Input()
  get open(): boolean {
    return this._open;
  }

  set open(value: boolean) {
    this._open = value;
    if (value) { this.nav.closeOtherLinks(this); }
  }

  // tslint:disable-next-line: variable-name
  protected _open: boolean;
  protected nav: AccordionDirective;

  constructor(@Inject(AccordionDirective) nav: AccordionDirective) {
    this.nav = nav;
  }

  ngOnInit(): any {
    this.nav.addLink(this);
  }

  ngOnDestroy(): any {
    this.nav.removeGroup(this);
  }

  toggle(): any {
    this.open = !this.open;
  }
}

手风琴锚指令

  import { Directive, HostListener, Inject } from '@angular/core';
import { AccordionLinkDirective } from './accordionlink.directive';

@Directive({
  selector: '[appAccordionToggle]'
})
export class AccordionAnchorDirective {

  protected navlink: AccordionLinkDirective;

  constructor( @Inject(AccordionLinkDirective) navlink: AccordionLinkDirective) {
    this.navlink = navlink;
  }

  @HostListener('click', ['$event'])
  onClick(e: any) {
    this.navlink.toggle();
  }
}

HTML

<mat-sidenav-container class="app">
  <mat-sidenav mode="side" opened color="primary" class="sidenav dark sidebar-panel app-inner">
    <div fxLayout="row wrap" fxLayoutAlign="center center">
        <button mat-icon-button>
            <mat-icon class="material-icons-round">menu</mat-icon>
        </button>
    </div>

    <!-- MENU /////////////////////////////////////////////////////////////////// -->


    <mat-nav-list appAccordion class="navigation navlist" role="list">
        <mat-list-item appAccordionLink *ngFor="let menuitem of menu" [group]="menuitem.state" class="module-link" role="listitem">

            <!-- LINK  -->
            <a appAccordionToggle class="relative" [id]="menuitem.state" [routerLink]="['/', menuitem.state]"
                *ngIf="menuitem.type === 'link'">
                <mat-icon *ngIf="menuitem.iconType==='icon'" class="material-icons-round">{{ menuitem.icon }}
                </mat-icon>
                <mat-icon *ngIf="menuitem.iconType==='svg'"><svg class="svg-24" viewBox="0 0 24 24">
                        <path fill="currentColor" [attr.d]="menuitem.icon" /></svg></mat-icon>
                <span>{{ menuitem.name }}</span>
                <span fxFlex></span>
              </span>
            </a>

            <!-- SUB LINK  -->
            <a appAccordionToggle class="relative" [id]="menuitem.state" href="javascript:;"
                *ngIf="menuitem.type === 'sub'">
                <mat-icon *ngIf="menuitem.iconType==='icon'" class="material-icons-round">{{ menuitem.icon }}
                </mat-icon>
                <mat-icon *ngIf="menuitem.iconType==='svg'"><svg class="svg-24" viewBox="0 0 24 24">
                        <path fill="currentColor" [attr.d]="menuitem.icon" /></svg></mat-icon>
                <span>{{ menuitem.name}}</span>
                <span fxFlex></span>
                <span class="menu-badge mat-{{ badge.type }}" *ngFor="let badge of menuitem.badge">{{ badge.value }}</span>
                <mat-icon class="menu-caret">arrow_drop_down</mat-icon>
            </a>
            <mat-nav-list class="sub-menu" *ngIf="menuitem.type === 'sub'">
                <mat-list-item *ngFor="let childitem of menuitem.children" routerLinkActive="open">
                    <a [routerLink]="['/', childitem.state ]" class="relative">
                        <mat-icon *ngIf="childitem.iconType==='icon'" class="material-icons-round">
                            {{ childitem.icon }}</mat-icon>
                        <mat-icon *ngIf="childitem.iconType==='svg'"><svg class="svg-24" viewBox="0 0 24 24">
                                <path fill="currentColor" [attr.d]="childitem.icon" /></svg></mat-icon>
                        <span>{{ childitem.name }}</span>
                    </a>
                </mat-list-item>
            </mat-nav-list>

        </mat-list-item>
    </mat-nav-list>

</mat-sidenav>
<mat-sidenav-content>
    Content
</mat-sidenav-content>

SCSS

我的 SCSS 太大 ---- 在此处下载文件 ---> https://github.com/Chej0/accordion-style

【问题讨论】:

  • 首先,请考虑将您的代码复制并粘贴到问题本身,而不是提供您的代码的屏幕截图,因为它可能不容易阅读,或者可能无法加载给较差的用户互联网连接。其次,请考虑为您的 SCSS 文件提供 GitHub Gist,而不是下载到看起来可疑的 URL。
  • @Edric 非常感谢您的反馈。我刚刚根据您的建议更新了信息
  • 您能否提供一个在 stackblitz 中可重现的最小示例?

标签: html css angular sass angular-material


【解决方案1】:

尝试更改您的 scss right here in yellow。如果我理解正确,您只是使用了display:block 而不是display:flex

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2015-06-25
    相关资源
    最近更新 更多