ng-click-outside:即使对于子元素,点击外部也会被触发

ng-click-outside: Click outside gets fired even for child elements

我想在点击容器外时执行一些任务。 为此,我使用了 ng-click-outside 指令。除一种情况外,它工作正常。在容器内,我有一个图标,它会在点击时切换;但是即使 clickOutside 事件也会被触发。

我认为问题是 ng-click-outside 检查容器中是否存在目标元素,但它没有找到它,因为我有 切换元素 在我的容器中。

这个问题有破解方法吗?

我在这里附上了一个例子 https://stackblitz.com/edit/primeng-treetablesections-demo-nznnjo?file=src/app/app.component.html

该指令有一个 属性 [exclude] 我们可以使用。问题是“人字形”,所以我们需要用 class .p-treetable-toggler.pi-fw 排除元素。我们可以想象只写

    <!--this NOT work-->
    <div class="tree" (clickOutside)="onClickedOutside($event)" 
       [exclude]="'.p-treetable-toggler,.pi-fw'">
       ....
    </div>

原因是指令没有检查这个 class 的元素,否则,当更改 [exclude] 时,存储这个 HTMLElements,并且每次我们点击时,检查这个元素。所以如果我们展开一个节点,这个“人字形”就不是store了。那么我们可以创建两个变量和一个函数

  exclude:string=null
  tog:boolean=false;

  toogle()
  {
    this.tog=!this.tog;
    this.exclude=this.tog?".p-treetable-toggler,.pi-fw":
                          ".p-treetable-toggler,.pi-fw,.fake"
  }

因此,我们每次 expand/collapsed 一个节点以及我们从服务

收到数据后调用此函数
     <!--and (onNodeExpand) and (onNodeCollapse) to the p-treeTable-->
     <p-treeTable (onNodeExpand)="toogle()" (onNodeCollapse)="toogle()" ...>

并且在 ngOnInit

ngOnInit(){
    this.nodeService.getFilesystem().then(files => {
      this.files = files
      setTimeout(()=>{
        this.toogle()
      })
    });
    ....
}

我们使用 setTimeout 告诉 Angular,“首先绘制结果,然后记得调用 this.toogle()”

可以看到your forked stackblitz

注意:如果我们只需要知道什么时候点击,如果我们点击一​​个元素,我们可以使用一些更简单的

如果我们有一个“div”

<div #mydiv>
  ...
</div>

我们可以使用ViewChildfromEvent rxjs

  @ViewChild('mydiv',{static:true}) element;

  fromEvent(document,'mousedown').pipe(map(
    res=>this.element.nativeElement.contains(res.target)
  )).subscribe(res=>{
     console.log(res)
  })

通常我们想要取消订阅 fromEvent,例如我们只在点击外面时,制作“东西”并取消订阅,所以如果使用过滤器并取(1):

  fromEvent(document,'mousedown').pipe(
    filter(res=>!this.element.nativeElement.contains(res.target)),
    take(1)
  ).subscribe(res=>{
     console.log('You click outSide')
  })