Angular 5 自定义指令触发包装到 *ngIf=false 中的元素
Posted
技术标签:
【中文标题】Angular 5 自定义指令触发包装到 *ngIf=false 中的元素【英文标题】:Angular 5 custom directive fires for element wrapped into *ngIf=false 【发布时间】:2019-01-27 13:07:19 【问题描述】:我正在研究应该在点击外部后关闭下拉菜单的指令。具有指令的元素也有*ngIf
并且在单击时不存在于页面上,但指令仍在触发事件 - 所以下拉菜单永远不会打开,因为showList
在(click)="showList = true"
之后立即变为false
被解雇了。我该如何避免这种情况?
stackblitz
import Directive, HostListener, ElementRef, EventEmitter, Inject, PLATFORM_ID, Output, Input, OnInit, Renderer2, AfterContentInit from '@angular/core';
import isPlatformBrowser from '@angular/common';
@Directive(
selector: '[clickOutside]'
)
export class ClickOutsideDirective implements AfterContentInit
ngAfterContentInit(): void
this.contentInitialized = true;
@Input("clickOutside") config: any = ;
@Output() clickOutside: EventEmitter<any> = new EventEmitter();
private isBrowser: boolean = false;
private isIE11: boolean = false;
private contentInitialized: boolean = false;
constructor(private renderer: Renderer2, private _el: ElementRef, @Inject(PLATFORM_ID) private platformId: any)
this.isBrowser = isPlatformBrowser(platformId);
this.isIE11 = this.isBrowser && !!(window as any).MSInputMethodContext && !!(document as any).documentMode;
@HostListener('document:click', ['$event'])
public onClick(event)
console.log("CLICKED");
if (this.contentInitialized && !(this._el.nativeElement.contains(event.target) || (event.target == window.document.querySelector(this.config.excludeLocator))))
this.clickOutside.emit(event);
@HostListener('document:keyup', ['$event'])
private onKeyup(event)
if (event.keyCode == 27)
this.clickOutside.emit(event);
<div class="menu-trigger" (click)="showList = true"></div>
<ul class="list" *ngIf="showList" (clickOutside)="showGiftList = false">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
【问题讨论】:
您的 html 不会在任何地方使用 clickOutside。在 StackBlitz 中发布一个完整的最小示例,重现问题。 你试过$event.stopPropagation();
吗?
@JBNizet 是的,错过了,这里是 stackblitz stackblitz.com/edit/…
@NasiruddinSaiyed 你想在.menu-trigger
上看到那个吗?似乎在工作stackblitz.com/edit/…
是的,它应该停止事件。
【参考方案1】:
为了避免父事件运行,您需要从子元素中停止它,您可以通过
$event.stopPropagation();
event.stopPropagation()
方法停止冒泡事件 父元素,防止任何父事件处理程序 执行。
如果您想学习一些基础知识并了解更多HTML 事件,您可以查看this。
【讨论】:
你知道从 Angular 的角度来看 - 为什么当*ngIf=flase
时它会被解雇?我认为如果元素不在 dom 中,它不应该接受任何交互
此时它实际上在 DOM 中。 1. 页面加载 - 不在 DOM 中 2. 点击触发器设置 showList = true
--> 在 DOM 中 3. 事件冒泡 4. 触发主机监听器 5. showList = false
--> 不再在 DOM 中以上是关于Angular 5 自定义指令触发包装到 *ngIf=false 中的元素的主要内容,如果未能解决你的问题,请参考以下文章