21

我已经使用自定义指令来检测角度 2 中元素外部的点击,但在角度 4 中则不可能。

[plunkr] https://plnkr.co/edit/aKcZVQ?p=info

当我尝试在 angular-4 中使用相同的代码时,出现以下错误:

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();
}

如果 Angular 4 中的指令声明有任何变化,请告诉我,官方文档对此事没有帮助。

4

1 回答 1

50

与您的 plnkr 相关的变化很少。

  1. NgModules,或者更确切地说看一下框架的架构。模块是您应该注册组件、服务和指令的地方
  2. 在模块中注册指令后,您不必在组件中导入它

该指令本身对我来说看起来不错。我将您的指令与在 Angular 4.3.5 中运行良好的指令进行了比较。

实际上,在这种情况下你不需要任何指令,除非它不会被重复使用。如果您只需要将该 clickOutside 应用于菜单,最好这样做:

像这样将点击事件绑定到您的“内部”选择器。假设这是您的菜单:

  <ul id="menu" (click)="clickedInside($event)"> <li> .. </li> </ul>

然后在你的组件中添加clickedInside()这样的函数:

  clickedInside($event: Event){
    $event.preventDefault();
    $event.stopPropagation();  // <- that will stop propagation on lower layers
    console.log("CLICKED INSIDE, MENU WON'T HIDE");
  }

最后,您可以在组件中使用Host Listener将 click 也绑定到文档的其余部分

  @HostListener('document:click', ['$event']) clickedOutside($event){
    // here you can hide your menu
    console.log("CLICKED OUTSIDE");
  }
于 2017-09-02T06:30:41.027 回答