指令点击外部 angular 6
directive click outside angular 6
我将 Angular 从 4 升级到 6,因此我的点击关闭政策出现问题,所有组件都停止工作。
我的指令:
import { Directive, Output, EventEmitter, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[clickOutside]'
})
export class ClickOutsideDirective {
constructor(private _elementRef : ElementRef) { }
@Output()
public clickOutside = new EventEmitter();
@HostListener('document:click', ['$event.target'])
public onClick(targetElement) {
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
if (!clickedInside) {
this.clickOutside.emit(null);
}
}
}
我的 component.html 使用了这个指令:
<div
id="sidenav"
*ngIf="this.opened"
class="sidenav"
[ngClass]="getClasses()"
[ngStyle]="getStyles()"
clickOutside
(clickOutside)="closeOutsideSidenav()"
>
<header> {{ navTitle }} </header>
<i
*ngIf="this.showCloseButton"
class="iconic iconic-x-thin close-icon"
(click)="closeSidenav()"
></i>
<ng-content></ng-content>
</div>
<div
*ngIf="this.backdrop && this.opened"
class="sidenav-backdrop"
></div>
您在模板中引用了 "this",这是不必要的。我做了一个该指令的工作示例:
https://stackblitz.com/edit/angular-piqewb
并且没有理由将 div 上的指令设置两次。
<div id="sidenav" *ngIf="opened" class="sidenav" [ngClass]="getClasses()" [ngStyle]="getStyles()" (clickOutside)="closeOutsideSidenav()">
<header> {{ navTitle }} </header>
<i *ngIf="showCloseButton" class="iconic iconic-x-thin close-icon" (click)="closeSidenav()"></i>
<ng-content></ng-content>
</div>
<div *ngIf="backdrop && opened" class="sidenav-backdrop"></div>
运行里面NgZone
.
示例:
export class AppComponent {
opened: boolean = false;
constructor(private ngZone: NgZone) {
}
closeOutsideSidenav(e) {
this.ngZone.run(() => {
this.opened = !this.opened;
})
}
}
我将我的代码添加到 stackblitz。 https://stackblitz.com/edit/angular-gyhtym(点击 "Highlight Me!" 之外)
查看:
<div #insideElement></div>
分量:
export class SomeClass {
@ViewChild("insideElement") insideElement;
@HostListener('document:click', ['$event.target'])
public onClick(targetElement) {
const clickedInside = this.insideElement.nativeElement.contains(targetElement);
if (!clickedInside) {
console.log('outside clicked');
}
}
}
这是对上述@YoungHyeong Ryu 回答的修改,但取消订阅,以便在卸载组件时处理程序停止工作。
演示 https://stackblitz.com/edit/angular-1q4pga
import { Component, Input, OnInit, OnDestroy, ViewChild } from '@angular/core';
@Component({
selector: 'app-click-outside',
template: `<div #insideElement>Click outside me.</div>`
})
export class ClickOutsideComponent implements OnInit, OnDestroy {
@ViewChild('insideElement', { static: false }) insideElement;
public ngOnInit() {
this.onDocumentClick = this.onDocumentClick.bind(this);
document.addEventListener('click', this.onDocumentClick);
}
public ngOnDestroy() {
document.removeEventListener('click', this.onDocumentClick);
}
protected onDocumentClick(event: MouseEvent) {
if (this.insideElement.nativeElement.contains(event.target)) {
return;
}
console.log('Clicked outside!');
}
}
在这里,我们删除了销毁时的事件侦听器。
此外,通常由 addEventListener 添加的方法在全局上下文中执行(而不是 this
上下文);所以我们应该处理它并将 onDocumentClick
方法绑定到 this
(我们在 ngOnInit
中这样做)。现在我们可以在 onDocumentClick
.
中使用 this
我将 Angular 从 4 升级到 6,因此我的点击关闭政策出现问题,所有组件都停止工作。
我的指令:
import { Directive, Output, EventEmitter, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[clickOutside]'
})
export class ClickOutsideDirective {
constructor(private _elementRef : ElementRef) { }
@Output()
public clickOutside = new EventEmitter();
@HostListener('document:click', ['$event.target'])
public onClick(targetElement) {
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
if (!clickedInside) {
this.clickOutside.emit(null);
}
}
}
我的 component.html 使用了这个指令:
<div
id="sidenav"
*ngIf="this.opened"
class="sidenav"
[ngClass]="getClasses()"
[ngStyle]="getStyles()"
clickOutside
(clickOutside)="closeOutsideSidenav()"
>
<header> {{ navTitle }} </header>
<i
*ngIf="this.showCloseButton"
class="iconic iconic-x-thin close-icon"
(click)="closeSidenav()"
></i>
<ng-content></ng-content>
</div>
<div
*ngIf="this.backdrop && this.opened"
class="sidenav-backdrop"
></div>
您在模板中引用了 "this",这是不必要的。我做了一个该指令的工作示例:
https://stackblitz.com/edit/angular-piqewb
并且没有理由将 div 上的指令设置两次。
<div id="sidenav" *ngIf="opened" class="sidenav" [ngClass]="getClasses()" [ngStyle]="getStyles()" (clickOutside)="closeOutsideSidenav()">
<header> {{ navTitle }} </header>
<i *ngIf="showCloseButton" class="iconic iconic-x-thin close-icon" (click)="closeSidenav()"></i>
<ng-content></ng-content>
</div>
<div *ngIf="backdrop && opened" class="sidenav-backdrop"></div>
运行里面NgZone
.
示例:
export class AppComponent {
opened: boolean = false;
constructor(private ngZone: NgZone) {
}
closeOutsideSidenav(e) {
this.ngZone.run(() => {
this.opened = !this.opened;
})
}
}
我将我的代码添加到 stackblitz。 https://stackblitz.com/edit/angular-gyhtym(点击 "Highlight Me!" 之外)
查看:
<div #insideElement></div>
分量:
export class SomeClass {
@ViewChild("insideElement") insideElement;
@HostListener('document:click', ['$event.target'])
public onClick(targetElement) {
const clickedInside = this.insideElement.nativeElement.contains(targetElement);
if (!clickedInside) {
console.log('outside clicked');
}
}
}
这是对上述@YoungHyeong Ryu 回答的修改,但取消订阅,以便在卸载组件时处理程序停止工作。
演示 https://stackblitz.com/edit/angular-1q4pga
import { Component, Input, OnInit, OnDestroy, ViewChild } from '@angular/core';
@Component({
selector: 'app-click-outside',
template: `<div #insideElement>Click outside me.</div>`
})
export class ClickOutsideComponent implements OnInit, OnDestroy {
@ViewChild('insideElement', { static: false }) insideElement;
public ngOnInit() {
this.onDocumentClick = this.onDocumentClick.bind(this);
document.addEventListener('click', this.onDocumentClick);
}
public ngOnDestroy() {
document.removeEventListener('click', this.onDocumentClick);
}
protected onDocumentClick(event: MouseEvent) {
if (this.insideElement.nativeElement.contains(event.target)) {
return;
}
console.log('Clicked outside!');
}
}
在这里,我们删除了销毁时的事件侦听器。
此外,通常由 addEventListener 添加的方法在全局上下文中执行(而不是 this
上下文);所以我们应该处理它并将 onDocumentClick
方法绑定到 this
(我们在 ngOnInit
中这样做)。现在我们可以在 onDocumentClick
.
this