【问题标题】:Click outside custom context menu to close it单击自定义上下文菜单外部以将其关闭
【发布时间】:2021-05-24 23:15:32
【问题描述】:

在菜单外单击时如何关闭自定义上下文菜单?

假设自定义简化上下文菜单是打开的。在上下文菜单之外的任何按钮单击都应关闭上下文菜单并触发按钮操作。

您可以在许多 stackoverflow 帖子中找到此自定义上下文菜单。它工作得很好。您可以找到一个工作示例via this nice short StackBlitz example。只需启动示例,右键单击以打开自定义上下文菜单。现在尝试通过单击菜单外部来关闭该上下文菜单。

简而言之,简化的 CUSTOM 上下文菜单是:

<div class="contextmenu" [ngStyle]="{'left.px': x, 'top.px': y}">
  this is your contextmenu content
</div>

附上代码:

@Component({
  selector: 'app-contextmenu',
  templateUrl: './contextmenu.component.html',
  styleUrls: ['./contextmenu.component.css']
})
export class ContextmenuComponent implements OnInit {
  constructor() { }
  ngOnInit() {}
  @Input() x=0;
  @Input() y=0;
}

父母:

<div (click)="disableContextMenu()" oncontextmenu="return false;">
    <ul>
        <li (contextmenu)="onrightClick($event)">right click me!</li>
    </ul>
    <div *ngIf="contextmenu==true">
        <app-contextmenu [x]="contextmenuX" [y]="contextmenuY"></app-contextmenu>
    </div>
</div>

用逻辑:

  contextmenu = false;
  contextmenuX = 0;
  contextmenuY = 0;

  onrightClick(event) {
    this.contextmenuX = event.clientX
    this.contextmenuY = event.clientY
    this.contextmenu = true;
  }
  disableContextMenu() {
    this.contextmenu = false;
  }

【问题讨论】:

  • 谢谢。当在另一个按钮上完成上下文菜单之外的单击时,该单击会同时触发 (clickOutside)=handler($event) 和按钮吗?
  • 是的,它会触发外部点击上下文菜单和按钮点击按钮没有任何问题
  • 附加文档监听器的常用方法对您不起作用?

标签: angular


【解决方案1】:

感谢您提出了很好的建议!基于不同解决方案的部分,我终于能够综合出一个优雅的解决方案。非常欢迎进一步改进!

在上下文菜单外部单击时,上下文菜单将关闭。当打开上下文菜单并单击一个按钮(左右)时,仍然可以工作并且打开的上下文菜单已关闭。

自定义上下文菜单:布局:无变化:

<div class="contextmenu" [ngStyle]="{'left.px': x, 'top.px': y}">
    <ul class="list-group">
        <li class="list-group-item" *ngFor="let menuItem of theMenuItems">
            <span (click)="outputSelectedMenuItem( menuItem)">{{ menuItem }}</span>
        </li>
    </ul>
</div>

自定义上下文菜单:逻辑 -- 更改标记:

@Component({
    selector: 'app-contextmenu',
    templateUrl: './contextmenu.component.html',
    styleUrls: ['./contextmenu.component.css']
})
export class ContextmenuComponent implements OnInit {
    @Input() x = 0;
    @Input() y = 0;
    @Input() menuitems = '';
    theMenuItems = [];
    @Output() menuItemSelected = new EventEmitter();
    // ADDED: 
    @Output() clickedOutside = new EventEmitter();

    // CHANGED: 
    constructor(private eRef: ElementRef) {}

    ngOnInit() {
        this.theMenuItems = this.menuitems.split(';');
    }

    // ADDED: 
    @HostListener('document:click', ['$event'])
    clickout(event) {
        if (!this.eRef.nativeElement.contains(event.target)) {
            this.menuItemSelected.emit();
        }
    }

    outputSelectedMenuItem(menuitem: string) {
        this.menuItemSelected.emit(menuitem);
    }
}

父级:仅上下文菜单布局:添加:clickedOutside

<div *ngIf="contextmenu===true">
  <app-contextmenu [x]="contextmenuX" [y]="contextmenuY" [menuitems]="showMenuOptions()"
                   (clickedOutside)="clickedOutsideMenu()"
                   (menuItemSelected)="handleMenuSelection2($event)"></app-contextmenu>
</div>

父:逻辑:

// Added: 
clickedOutsideMenu() {
    this.disableContextMenu();
}

@HostListener('window:resize', ['$event'])
onResize(event) {
    this.innerWidth = window.innerWidth;
    this.innerHeight = window.innerHeight;
}

showMenuOptions() {
    return 'Menu option 1;Menu option 2';
}

onrightClick(event, parameter1: number, parameter2: string) {
    this.contextmenuX = event.clientX - 100;
    this.contextmenuY = event.clientY;
    this.contextmenu = true;
    //... save the parameters ... here parameter1 and parameter2
    const menuHeight = this.showMenuOptions().split(';').length;
    const maxY = this.innerHeight - (menuHeight * 30);
    if (this.contextmenuY > maxY) {
        this.contextmenuY = maxY;
    }
    event.preventDefault();
    event.stopPropagation();
    return false;
}

disableContextMenu() {
    this.contextmenu = false;
}

handleMenuSelection2(menuselection: string) {
    this.errorMessage = '';
    if (menuselection === 'Menu option 1') {
        this.requestRapportageSetToFailure();
    } else if (menuselection === 'Menu option 2') {
        this.requestRapportageRestart();
    }
    this.contextmenu = false;
}

【讨论】:

    猜你喜欢
    • 2016-04-24
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多