web-dev-qa-db-ja.com

コンテキストメニューとしてマットメニューを使用する:開いたマットメニューを閉じる方法を閉じて、別の場所で開きます。

角度:v8.2.8

私はMAT-MENU(Angular素材)を使用してコンテキストメニューをエミュレートすることを管理します。私のページ上での右クリックすると、メニューがマウスの場所に表示されます。

私が達成したいもの:マウスをページ上の別の場所に移動すると、もう一度右クリックします。元の場所のメニューが新しい場所で閉じて再び開くことを期待していました。

しかし実際には右クリックすると、何も起こらず、元の場所のメニューは開いたままです。

実際、私は最初にクリックしてオープンのメニューを元の場所に閉じてください。その後に新しいマウスの場所でメニューを開くために右クリックします。

質問:私が欲しいものを達成する方法は何ですか?

@Component({
  selector: 'fl-home',
  template:`
 <mat-menu #contextmenu>
      <div >
           <button mat-menu-item>Clear all Paths</button>
       </div>
  </mat-menu>
  <div [matMenuTriggerFor]="contextmenu" [style.position]="'absolute'" [style.left.px]="menuX" [style.top.px]="menuY" ></div>
  
  <div class="container" (contextmenu)="onTriggerContextMenu($event);"> ....</div>
`})
export class HomeComponent  {

    menuX:number=0
    menuY:number=0

    @ViewChild(MatMenuTrigger,{static:false}) menu: MatMenuTrigger; 
    
   
    onTriggerContextMenu(event){
        
      event.preventDefault();
      this.menuX = event.x - 10;
      this.menuY = event.y - 10;
      this.menu.closeMenu() // close existing menu first.
      this.menu.openMenu()

    }
}
 _
6
Bruce

私の解決策

  ngOnInit(): void {
    this.windowClickSubscription = fromEvent(window, 'click').subscribe((_) => {
      if (this.contextMenu.menuOpen) {
        this.contextMenu.closeMenu();
      }
    });
  }
  ngOnDestroy(): void {
    this.windowClickSubscription && this.windowClickSubscription.unsubscribe();
    this.menuSubscription && this.menuSubscription.unsubscribe();
  }
  onContextMenu(event: MouseEvent){
    event.preventDefault();
    this.menuSubscription && this.menuSubscription.unsubscribe();
    this.menuSubscription = of(1)
      .pipe(
        tap(() => {
          if (this.contextMenu.menuOpen) {
            this.contextMenu.closeMenu();
          }
          this.contextMenuPosition.x = event.clientX;
          this.contextMenuPosition.y = event.clientY;
        }),
        // delay(this.contextMenu.menuOpen ? 200 : 0),
        delayWhen((_) => (this.contextMenu.menuOpen ? interval(200) : of(undefined))),
        tap(async() => {
          this.contextMenu.openMenu();
          let backdrop: HTMLElement = null;
          do {
            await this.delay(100);
            backdrop = document.querySelector(
              'div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing'
            ) as HTMLElement;
          } while (backdrop === null);
          backdrop.style.pointerEvents = 'none';
        })
      )
      .subscribe();
  }
  delay(delayInms: number) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(2);
      }, delayInms);
    });
  }
 _

https://stackblitz.com/edit/angular-ivy-udzyez

1
Jay

多分あなたはそれを解決しました、しかし、ここに私のこの問題への私のアプローチです:divのサラウンドメニュー項目、そしてマウスの葉のメニュー(そのdiv)がそれを閉じるので、もう一度それを再度右折することができます。 ....

<div (mouseleave)="mouseLeaveMenu()">
  ...menu items...
</div>
...
mouseLeaveMenu() {
  if (this.contextMenu.menuOpened) this.contextMenu.closeMenu();
}
 _
0
Ivica Buljević