@plrov

Как блокировать @HostListener прослушку?

Доброго дня!

Есть компонент, что с помощью @HostListener слушает нажатия клавиш Escape & Enter. Где-то (не в коде компонента) может динамически создасться MatDialog (диалоговое окно из Angular Material). Теперь борозды управления переходят к нему - и Escape служит для закрытия диалогового окна, а Enter для клика по основной кнопке диалогового окна.

Вопрос - как на время открытого диалогового окна блокировать прослушку @HostListener из компонента?

Рассматривался вариант со статической переменной внутри класса компонента диалогового окна, например, dialogOpened = false, которая бы становилась true на этапе OnInit и обратно false на этапе OnDestroy. Однако в данном случае необходим setTimeout в OnDestroy, который к тому же не всегда гарантирует, что на момент прослушки в компоненте диалоговое окно еще не закрылось.
  • Вопрос задан
  • 144 просмотра
Решения вопроса 2
Xuxicheta
@Xuxicheta
инженер
Не совсем понял момент насчет setTimeout.
В коде мат-диалога есть такое
// The logic that disposes of the overlay depends on the exit animation completing, however
      // it isn't guaranteed if the parent view is destroyed while it's running. Add a fallback
      // timeout which will clean everything up if the animation hasn't fired within the specified
      // amount of time plus 100ms. We don't need to run this outside the NgZone, because for the
      // vast majority of cases the timeout will have been cleared before it has the chance to fire.
this._closeFallbackTimeout = setTimeout(() => {
        this._overlayRef.dispose();
      }, event.totalTime + 100);

overlayRef.dispose() производит отвязывание от событий клавиатуры.
Как я понял вы по той же причине хотите таймаут, т.к. видимо OnDestroy срабатывает раньше отписок, хотя по коду должен бы после.
Материал довольно сложно устроен и я не стал бы на это полагаться :)

Не проще ли сделать глобальный серсвис с событями клавиатуры, диалоговые окна запускать с disableClose: true, при открытие окна блокировать события сервиса для всех, кроме диалога, а сам диалог закрывать руками при получении события эскейпа и сразу снимать блокирование?
Ответ написан
@plrov Автор вопроса
Дополнительное решение:

public constructor(private readonly dialog: MatDialog) {  }
...
@HostListener("document:keydown", ["$event"]) onKeydownHandler(event: KeyboardEvent) {
        if (event.key === "Escape") {
            if (this.dialog.openDialogs.length) {
                return;
            }

            /* Do something */
        }
    }
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы