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()”
注意:如果我们只需要知道什么时候点击,如果我们点击一个元素,我们可以使用一些更简单的
如果我们有一个“div”
<div #mydiv>
...
</div>
我们可以使用ViewChild
和fromEvent
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')
})
我想在点击容器外时执行一些任务。 为此,我使用了 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()”
注意:如果我们只需要知道什么时候点击,如果我们点击一个元素,我们可以使用一些更简单的
如果我们有一个“div”
<div #mydiv>
...
</div>
我们可以使用ViewChild
和fromEvent
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')
})