如何使用指令停止事件传播?
How to stop event propagation using directive?
我有一个指令仅在其他 angular 应用程序中有效,但在 Ionic 中 angular 它不起作用。
该指令检查用户是否已登录,如果没有,则打开带有一些说明的弹出窗口。
当用户未登录时,我有弹出窗口并且可以正常工作,但是尽管有 preventDefault/stopPropagation 等等,事件还是被触发了。
这是代码:
View.component.html
<ion-icon name="pricetag-outline" onlyLogged authorized="true" (click)="saveNews(news)" ></ion-icon>
仅-logged.directive.ts
import { Directive, ElementRef, OnInit, HostListener, Input } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { AuthService } from '../services/auth.service';
import { OnlyLoggedComponent } from '../components/only-logged/only-logged.component';
@Directive({
selector: '[onlyLogged]'
})
export class OnlyLoggedDirective implements OnInit {
@Input() authorized = false;
isUserLogged: boolean;
constructor(private auth: AuthService, public popoverController: PopoverController) { }
@HostListener('click', ['$event'])
clickEvent(event) {
if (!this.isUserLogged) {
console.log(event);
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
event.returnValue = false;
event.buttonDisabled = true;
this.openLogin(event);
return false;
}
}
ngOnInit() {
this.auth.isAuthenticated.subscribe((authenticated) => {
this.isUserLogged = authenticated;
});
}
async openLogin(ev: any) {
const popover = await this.popoverController.create({
component: OnlyLoggedComponent,
event: ev,
translucent: true,
animated: true,
size: 'auto'
});
await popover.present();
const { role } = await popover.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
}
离子版本:6.18.1
Angular:13.0.3
节点:16.13.2
我进行了很多搜索,但没有找到解决方案...有人可以告诉我我做错了什么吗?
根据您的问题,我了解到您正在尝试使用 @HostListener
指令拦截点击事件。
我实际上也无法使用 hostlistener 使这个请求的行为起作用。
在我看来,问题是 stopPropagation
在 bubbling
模式下会阻止事件从子级触发到父级。
但问题是您试图根据某些条件阻止点击元素本身。
换句话说你需要恰恰相反,你需要在capturing mode
中应用stopPropagation
,从父到子
我的建议是使用rxjs fromEvent
- https://rxjs.dev/api/index/function/fromEvent
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
@Directive({
selector: '[onlyLogged]'
})
export class OnlyLoggedDirective {
sub = new Subscription();
logged: boolean = true;
constructor(private elRef: ElementRef) {}
ngOnInit() {
const el = this.elRef.nativeElement;
this.sub = fromEvent(el.parentNode, 'click', { capture: true})
.subscribe( (ev: any) => {
if(ev.target == el) { this.checkLogin(ev); }
})
}
checkLogin(ev: any) {
if(!this.logged) {
console.log("user is not logged in", );
ev.stopImmediatePropagation();
this.openLogin(ev);
} else {
console.log("user is logged in");
}
}
openLogin(ev: any) {
console.log('onDidDismiss resolved with role');
}
}
<ion-content [fullscreen]="true">
<div onlyLogged (click)="run()">click on me</div>
</ion-content>
run() {
console.log("This click has to be prevented, when user is not logged in");
}
我有一个指令仅在其他 angular 应用程序中有效,但在 Ionic 中 angular 它不起作用。
该指令检查用户是否已登录,如果没有,则打开带有一些说明的弹出窗口。
当用户未登录时,我有弹出窗口并且可以正常工作,但是尽管有 preventDefault/stopPropagation 等等,事件还是被触发了。
这是代码:
View.component.html
<ion-icon name="pricetag-outline" onlyLogged authorized="true" (click)="saveNews(news)" ></ion-icon>
仅-logged.directive.ts
import { Directive, ElementRef, OnInit, HostListener, Input } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { AuthService } from '../services/auth.service';
import { OnlyLoggedComponent } from '../components/only-logged/only-logged.component';
@Directive({
selector: '[onlyLogged]'
})
export class OnlyLoggedDirective implements OnInit {
@Input() authorized = false;
isUserLogged: boolean;
constructor(private auth: AuthService, public popoverController: PopoverController) { }
@HostListener('click', ['$event'])
clickEvent(event) {
if (!this.isUserLogged) {
console.log(event);
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
event.returnValue = false;
event.buttonDisabled = true;
this.openLogin(event);
return false;
}
}
ngOnInit() {
this.auth.isAuthenticated.subscribe((authenticated) => {
this.isUserLogged = authenticated;
});
}
async openLogin(ev: any) {
const popover = await this.popoverController.create({
component: OnlyLoggedComponent,
event: ev,
translucent: true,
animated: true,
size: 'auto'
});
await popover.present();
const { role } = await popover.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
}
离子版本:6.18.1 Angular:13.0.3 节点:16.13.2
我进行了很多搜索,但没有找到解决方案...有人可以告诉我我做错了什么吗?
根据您的问题,我了解到您正在尝试使用 @HostListener
指令拦截点击事件。
我实际上也无法使用 hostlistener 使这个请求的行为起作用。
在我看来,问题是 stopPropagation
在 bubbling
模式下会阻止事件从子级触发到父级。
但问题是您试图根据某些条件阻止点击元素本身。
换句话说你需要恰恰相反,你需要在capturing mode
中应用stopPropagation
,从父到子
我的建议是使用rxjs fromEvent
- https://rxjs.dev/api/index/function/fromEvent
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
@Directive({
selector: '[onlyLogged]'
})
export class OnlyLoggedDirective {
sub = new Subscription();
logged: boolean = true;
constructor(private elRef: ElementRef) {}
ngOnInit() {
const el = this.elRef.nativeElement;
this.sub = fromEvent(el.parentNode, 'click', { capture: true})
.subscribe( (ev: any) => {
if(ev.target == el) { this.checkLogin(ev); }
})
}
checkLogin(ev: any) {
if(!this.logged) {
console.log("user is not logged in", );
ev.stopImmediatePropagation();
this.openLogin(ev);
} else {
console.log("user is logged in");
}
}
openLogin(ev: any) {
console.log('onDidDismiss resolved with role');
}
}
<ion-content [fullscreen]="true">
<div onlyLogged (click)="run()">click on me</div>
</ion-content>
run() {
console.log("This click has to be prevented, when user is not logged in");
}