Angular:使用ngFor inside检测div内的click事件

时间:2016-07-04 14:10:11

标签: javascript dom typescript angular

我正在处理一个包含大量下拉菜单的应用程序,我希望能够在每次点击发生之外关闭下拉列表。

我找到了一些很好的解决方案,但没有一个处理其中包含ngFor的情况,当我在ngFor中记录click事件目标时,我得到了元素,但是这个没有任何父元素。我无法用'find'或'contains'来检测它。

是否有人有解决方案来检测此目标是否属于下拉列表?

指令

import {
Directive,
ElementRef,
EventEmitter,
Input,
OnInit,
Output,
SimpleChange
} from '@angular/core';

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

constructor(private _el:ElementRef) {
    this.onClickBody = this.onClickBody.bind(this);
}

ngOnInit() {
    document.body.addEventListener('click', this.onClickBody);
}

private onClickBody(e:Event) {
    if (!this.isClickInElement(e)) {
        this.clickOutside.emit(e);
    }
}

private isClickInElement(e:any):boolean {
    var current = e.target;
    do {
        console.log(current);
        if ( current === this._el.nativeElement ) {
            return( true );
        }
        current = current.parentNode;
    } while ( current );
    return false;
}
}

我调用指令

的示例
   <div (clickOutside)="onClickedOutside($event)">
            <ul>
                <li *ngFor="let item of itemsList" (click)="selectItem(item)">
                  <span class="item">
                    {{item.name}}
                  </span>
                </li>
            </ul>
        </div>

当我点击item.name,console.log(当前);给我回两行

<span>Item</span>


<li>
  <span>Item</span>
</li>

2 个答案:

答案 0 :(得分:2)

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

  constructor(private _eref: ElementRef) { }

  @HostListener('window:click')
  private onClickBody(e:Event) {
    if (!this.isClickInElement(e)) {
        this.clickOutside.emit(e);
    }
  }

  private isClickInElement(e:any):boolean {
    return this._eref.nativeElement.contains(event.target);
  }
}

另见https://stackoverflow.com/a/35713421/217408

答案 1 :(得分:1)

此解决方案适用于Chrome,但遗憾的是不适用于IE。我还在寻找另一种方法来做到这一点

 private isClickInElement(e:any):boolean {
    var current = e.target;
    if(current == this._el.nativeElement) {
        return true;
    }
    for(let parentKey in e.path) {
        if(e.path[parentKey] == this._el.nativeElement) {
            return true;
        }
    }

    return false;
}