【问题标题】:How to prevent angular material mat-menu from closing?如何防止角材料垫菜单关闭?
【发布时间】:2018-04-08 15:24:15
【问题描述】:

我正在角度材料中创建一个日期时间选择器控件,并使用以下代码来执行此操作

<button mat-button [matMenuTriggerFor]="menu">
    <mat-icon>date_range</mat-icon>
    <span>Date Range</span>
</button>
<mat-menu #menu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column">
            <button (click)="setInterval(15)" mat-menu-item>Last 15 minutes</button>
            <button (click)="setInterval(360)" mat-menu-item>Last 6 hours</button>
            <button (click)="setInterval(1440)" mat-menu-item>Last 24 hours</button>
            <button (click)="setInterval(2880)" mat-menu-item>Last 2 days</button>
            <button (click)="setInterval(10080)" mat-menu-item>Last 7 days</button>
            <button (click)="setInterval(-1)" [matMenuTriggerFor]="dateTimeMenu" mat-menu-item>Custom</button>
        </div>
        <mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
            <div fxLayout="row">
                <div fxLayout="column">
                    <b>From</b>
                    <mat-calendar></mat-calendar>
                </div>
                <div fxLayout="column">
                    <b>To</b>
                    <mat-calendar></mat-calendar>
                </div>
            </div>
        </mat-menu>
    </div>
</mat-menu>

目前,当我单击一个按钮时,它会关闭菜单。我知道我们可以对每个 mat-menu-item 执行 $event.stoppropagation() 以防止它关闭。

但我想知道 mat-calendar 是否可以这样做

正如您在上图中看到的,当前当我选择一个日期时,它正在关闭菜单。有没有可能防止这种情况发生?

【问题讨论】:

  • 您好,您成功制作了这样的日期范围选择器吗?我需要一个,但并没有心情重新发明轮子。

标签: javascript angular angular-material2


【解决方案1】:

您只需将(click) = "$event.stopPropagation()" 添加到这些日历的父元素即可。如下所示,

<mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column" (click)="$event.stopPropagation();">
            <b>From</b>
            <mat-calendar></mat-calendar>
        </div>
        <div fxLayout="column" (click)="$event.stopPropagation();">
            <b>To</b>
            <mat-calendar></mat-calendar>
        </div>
    </div>
</mat-menu>

Stackblitz demo.

【讨论】:

  • 似乎效果不佳。单击日期时无法选择日期
  • 它非常适合单个 div,但我想对整个 mat-menu 做同样的事情,这样无论用户在 mat-menu 内单击什么位置,它都不应该关闭,不幸的是 $event.stoppropagation() 不起作用整个菜单
  • 为我工作。我在 mat-menu 中添加了一个包装器 div,并在其上添加了 $event.stoppropagation()
  • mat-menu 中的复选框对我有用,非常感谢
  • 此解决方案的另一个问题是,当您单击父元素上的某个位置时,不会触发来自内部所有元素的 blur 之类的事件。这导致我mat-autocomplete 在父元素上单击其他位置时不会关闭,所以我必须找到另一个解决方案
【解决方案2】:

通过返回上一个解决方案,将指令封装在一个方法中允许不关闭菜单并继续执行指令

在 HTML 中:

<mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column" (click)="doSomething($event);">
            <b>From</b>
            <mat-calendar></mat-calendar>
        </div>
        <div fxLayout="column" (click)="doSomething($event)">
            <b>To</b>
            <mat-calendar></mat-calendar>
        </div>
    </div>
</mat-menu>

在 TS:

doSomething($event:any){
    $event.stopPropagation();
    //Another instructions
}

【讨论】:

    【解决方案3】:

    如果您想在单击 mat-menu-content 时停止关闭 mat-menu,我确实在锚标记而不是 mat-menu 上添加了 $event.stopPropogation()。 因此,即使单击表单上的任何位置,菜单对话框也不会关闭。

    Example:- 
        <mat-menu #nameAndDescriptioContextMenu="matMenu" [hasBackdrop]="false">
             <a (click)="$event.stopPropagation();$event.preventDefault();">
                   <div>
                     Form Group Form
                   </div> 
             </a> 
        </mat-menu>
    

    【讨论】:

    • 爱它,兄弟。干得好!
    【解决方案4】:

    你有很多选择,我邀请你尝试以下

        <mat-menu [hasBackdrop]="false">
         <div  (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
         ...
         </div>
        </mat-menu>
    

    [hasBackdrop]="false" 如果您想防止在单击框外任意位置时关闭 mat-menu,否则将其删除

    【讨论】:

      【解决方案5】:

      不幸的是,以上答案都不适合我。如果您需要菜单面板比内容宽得多,则没有可以放置"$event.stopPropagation();" 的位置,因此如果您单击 mat-menu-panel 它将关闭。 幸运的是,仍然有一种方法可以避免这种情况,通过“覆盖”click MatMenu 事件。 这里是 stackblitz 的例子,感谢我的同事:https://stackblitz.com/edit/mat-menu-disable-close

      ngAfterViewInit() {
          // Inject our custom logic of menu close
          (this.searchMenu as any).closed = this.searchMenu.close = this.configureMenuClose(this.searchMenu.close);
        }
      
      private configureMenuClose(old: MatMenu['close']): MatMenu['close'] {
          const upd = new EventEmitter();
          feed(upd.pipe(
            filter(event => {
              if (event === 'click') {
                // Ignore clicks inside the menu 
                return false;
              }
              return true;
            }),
          ), old);
          return upd;
        }
      }
      function feed<T>(from: Observable<T>, to: Subject<T>): Subscription {
        return from.subscribe(
          data => to.next(data),
          err => to.error(err),
          () => to.complete(),
        );
      }

      这样,只有在您单击外部(这很容易删除)并且使用触发器时,它才会关闭。 这是我在项目中想要的行为,我希望它对某人有用。

      【讨论】:

        【解决方案6】:

        你可以直接在你的组件中使用这个指令。

        在 HTML 中

        <mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
            <div fxLayout="row">
                <div fxLayout="column" mat-filter-item>
                    <b>From</b>
                    <mat-calendar></mat-calendar>
                </div>
                <div fxLayout="column" mat-filter-item >
                    <b>To</b>
                    <mat-calendar></mat-calendar>
                </div>
            </div>
        </mat-menu>
        

        将其保存为 filter.directive.ts 从“@angular/core”导入{指令、HostListener、HostBinding};

        @Directive({
          selector: "[mat-filter-item]"
        })
        export class FilterItemDirective {
          @HostListener("click", ["$event"])
          onClick(e: MouseEvent) {
            e.stopPropagation();
            e.preventDefault();
        
            return false;
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2018-12-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多