В браузере многие события всплывают (и событие click
является одним из них).Это означает, что событие идет от целевого элемента прямо вверх.И если вы зарегистрировали событие с тем же именем где-то выше, то оно будет запущено, несмотря на то, что произошло в целевом обработчике.
document =====================================================> outsideHandler
body /\
.... ||
<app-editable-inplace> bubbling
<div view> /\
<h3>Click to edit [not working :-( ]</h3> <===== target || viewClickHandler
</div>
...
</app-editable-inplace>
Итак, как вы уже догадались по этой причине, clickOutside$
запускается мгновенно.
Существуют различные способы исправить это:
1) Самый простой способ - использовать event.stopPropagation()
, чтобы событие не всплыло дальше.
private viewModeHandler() {
fromEvent(this.element, 'click').pipe(
untilDestroyed(this)
).subscribe((e: any) => {
console.log('clicked inside');
e.stopPropagation(); <==================== add this
2) Поскольку событие всплытия в этих обработчиках одинаковое, вы можете установить некоторый флаг, чтобы предотвратить его обработку в верхнем обработчике.
private viewModeHandler() {
fromEvent(this.element, 'click').pipe(
untilDestroyed(this)
).subscribe((e: any) => {
console.log('clicked inside');
e.fromInside = true;
...
const clickOutside$ = fromEvent(document, 'click').pipe(
filter((e: any) => {
return !e.fromInside && this.element.contains(e.target) === false
}),
3) Событие перехвата щелчка в фазе захвата:
fromEvent(this.element, 'click', { capture: true }).pipe(
...
const clickOutside$ = fromEvent(document, 'click', { capture: true })