web-dev-qa-db-ja.com

クリック処理を変更するAngular2ディレクティブ

特定の要素の動作を変更するAngular2属性ディレクティブを作成しようとしています。具体的には、クリックハンドラーを持つ特定の要素に属性を適用し、特定の条件下でバインドされた関数が実行されないようにします。

だから今私は要素を持っています例:

<button (click)="onClick(param1, param2)"></button>

onClickは、何らかの作業を行うボタン要素をホストするコンポーネントで宣言された関数です。

私がやりたいのは、次のようなものを書くことです。

<button (click)="onClick(param1, param2)" online-only></button>

次のようなディレクティブがあります。

@Directive({
  selector: '[online-only]',
})
export class OnlineOnlyDirective {
  @HostListener('click', ['$event']) 
  onClick(e) {
    if(someCondition){
      e.preventDefault();
      e.stopPropagation();
    }
  }
}

ただし、クリックハンドラーが最初に実行されるため、ディレクティブに実行を停止する機会が与えられません。

私が考えた2番目のアプローチは、(クリック)を独自のハンドラーeg([onlineClick] = "onClick")に置き換え、ディレクティブが適切と考えるときに渡された関数を実行することでしたが、この方法では、パラメーターをonClick関数に渡すことができず、少しです見るのが変だ。

そのようなことをすることについて何か考えはありますか?

8
masimplo

Angularに特定のイベントハンドラーを最初に実行させる方法がわかりません。回避策は、次のようなカスタムイベントを使用することです。

<button (myClick)="onClick(param1, param2)" online-only></button>
@Directive({
  selector: '[myClick]',
})
export class OnlineOnlyDirective {
  @Output() myClick: EventEmitter = new EventEmitter();
  @HostListener('click', ['$event']) 
  onClick(e) {
    if(someCondition){
      e.preventDefault();
      e.stopPropagation();
    } else {
      this.myClick.next(e);
    }
  }
}
13

これまでのところ、これはあなたが望む方法では不可能です((クリック)バインディングを使用するだけです)。これは、Angular->(クリック)バインディング、@ HostListnerを介して登録されたすべてのイベントが、単一のリスナーを介してプロキシされるためです。そのため、stopPropagationを呼び出すか、この場合はstopImmediatePropagationが機能しません。個別のイベントリスナーがなくなったため。詳細については、この問題を参照してください: https://github.com/angular/angular/issues/9587

1
wawka

最近、私がやりたかったのと同じようなことを経験しましたが、カスタムコンポーネントにクリックハンドラーがあったために、提案された回答が機能しませんでした。これが私がしたことです。

<button (myClick)="onClick(param1, param2)" online-only></button>

または

<my-cmp (myClick)="onClick(param1, param2)" online-only></my-cmp>

ディレクティブは次のようになります。

@Directive({
   selector: '[online-only]',
})
export class OnlineOnlyDirective implements OnInit {
   constructor(private el: ElementRef) { }

   ngOnInit() {
      if (someCondition) {
         this.el.nativeElement.removeAllListeners('click');
      }
   }
}

これにより、コンポーネントまたは要素のクリックイベントリスナーが削除されます。これは反応しないので、someConditionが変更された場合、クリックリスナーを元に戻す方法が必要です。ただし、このユースケースは必要ありませんでした。

更新

これは開発では機能しましたが、本番環境でコードが縮小されたときには機能しませんでした。

1
AliF50