I have used a custom directive to detect click outside an element in angular 2 but the same is not possible in angular 4.
[plunkr]
https://plnkr.co/edit/aKcZVQ?p=info
When I try using the same code in angular-4 I get the following errors:
1. Argument of type '{ template: string; directives: typeof ClickOutside[]; }' is not assignable to parameter of type 'Component'. ==>
@Component({
templateUrl: "",
directives: [ClickOutside]
})
2. Type 'Subscription' is not assignable to type 'Observable<MouseEvent>'. in the directive inside ngOnInit() and ngOnDestroy()
ngOnInit() {
this.globalClick = Observable
.fromEvent(document, 'click')
.delay(1)
.do(() => {
this.listening = true;
}).subscribe((event:MouseEvent) => {
this.onGlobalClick(event);
});
}
ngOnDestroy() {
this.globalClick.unsubscribe();
}
If there is any change in the directive declaration in angular 4 please let me know, the official docs are of no help in this matter.
There are few changes in relation to your plnkr.
The directive itself looks fine for me. I compared your directive with mine that works fine in Angular 4.3.5.
Actually, you don't need any directive in that case, unless it won't be used repetitive. If you need to apply that clickOutside only for menu it would be better to do sth like that:
Bind click event to your "inside" selector like that. Let's say it's your menu:
<ul id="menu" (click)="clickedInside($event)"> <li> .. </li> </ul>
then inside your component add clickedInside()
function like this:
clickedInside($event: Event){
$event.preventDefault();
$event.stopPropagation(); // <- that will stop propagation on lower layers
console.log("CLICKED INSIDE, MENU WON'T HIDE");
}
And finally you can use Host Listener in your component to bind click also to the rest of document
@HostListener('document:click', ['$event']) clickedOutside($event){
// here you can hide your menu
console.log("CLICKED OUTSIDE");
}