2个组件的角度2+“单击外部”,而不仅仅是1

时间:2019-01-18 20:32:26

标签: angular event-handling

我有一个多组件侧边栏开关,app / button / sidebar都在其自己的组件中,button / sidebar是应用的子级(或至少加载在应用程序组件中,假设这是子级)

在Angular的跨组件通信方面还不够快,在这种情况下,我正在使用服务。

我要做什么:如果未单击组件 button 侧边栏(这两个组件之外的任何内容)...,则折叠侧边栏。

目前,我正在服务中的“可见”变量上切换布尔状态以扩展/折叠导航。

我尝试了所有方法,但收效甚微。有什么方法可以做到这一点?或者至少在我能读到的地方可以靠近并从那里拿走它?

代码:https://stackblitz.com/edit/multi-component-communication

3 个答案:

答案 0 :(得分:1)

如果document:click事件处理程序切换了visible标志,则当前代码有效:

@HostListener("document:click", ["$event"])
onClick(event) {
  this.visible = this._ref.nativeElement.contains(event.target);
}

为防止按钮单击到达文档级别,请停止事件传播:

<toggle-sidebar (click)="$event.stopPropagation()"></toggle-sidebar>

有关演示,请参见this stackblitz

答案 1 :(得分:1)

您可以在侧边栏和按钮中处理clickOutSide。如果两者都在外部单击,请关闭侧边栏。您可以通过@ Output / EventEmitter在两个子组件中实现相同的目的,并在app.component.ts文件中收听它们。

所以,总结一下:

  1. 选中侧边栏中的clickOutSide,然后将其发送给父级,即app.component.ts
  2. 在切换按钮中选中clickOutSide,然后将其发送给父级,即app.component.ts
  3. app.component.ts中,上面的handle发出并执行检查:
    • 在外部单击切换按钮,在外部单击sidenav并打开sidenav时,我们应关闭sidenav。
    • 从内部单击切换按钮时,从功能上来讲,将在外部单击sidenav。但是,我们必须更改sidenav才能在内部单击。因此,我们将手动更改该标志。否则,如果您单击sidenav但在切换按钮之外,则会关闭sidenav。

考虑到上述情况,我已经编辑了您的堆叠here

答案 2 :(得分:0)

您应该使用指令来收听外部面板的点击:

import { Directive, ElementRef, EventEmitter, HostListener, Output } from '@angular/core';

@Directive({
    selector: '[clickOutside]'
})
export class ClickOutsideDirective {
    @Output() clickOutside: EventEmitter<Event> = new EventEmitter<Event>();

    constructor(private elementRef: ElementRef) { }

    @HostListener('document:mousedown', ['$event'])
    onDocumentClick(event: Event) {
        if (!this.isClickInElement(event)) {
            this.clickOutside.emit(event);
        }
    }

    private isClickInElement(event: Event): boolean {
        return this.elementRef.nativeElement.contains(event.target);
    }
}

现在您可以在菜单上附加此指令并绑定到其输出,然后调用该方法折叠边栏或执行操作。例如:

<ol (clickOutside)="collapseSideBar()">