I have a directive that works in other only angular application, but in Ionic with angular it doesn't.
The directive check if a user is logged, if not, open a popup with some instructions.
When a user is not logged in I have the popup and works, but the event is fired the same despite the preventDefault/stopPropagation etc.
This is the code:
View.component.html
<ion-icon name="pricetag-outline" onlyLogged authorized="true" (click)="saveNews(news)" ></ion-icon>
only-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);
}
}
Ionic Version: 6.18.1 Angular: 13.0.3 Node: 16.13.2
I made a lot of search but I didn't reach a solution... Someone can tell me what I did wrong?
CodePudding user response:
From your question I understood that you are trying to intercept a click event using @HostListener
directive.
I actually couldn't get this requested behaviour to work using the hostlistener either.
It seems to me the problem is that stopPropagation
in bubbling
mode prevents event firing from child to parent.
But the thing is that you are trying to prevent click on the element itself depending on some condition.
In other words you need exactly the opposite, you need to apply stopPropagation
in capturing mode
, from parent to child
My proposal is to use 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");
}