Как обнаружить щелчок за пределами элемента в Angular 7? - PullRequest
0 голосов
/ 03 июля 2018

Это div будет динамически отображаться на странице как восточная панель при нажатии кнопки open panel. Переменная bool showEastPanel используется для открытия и закрытия восточной панели. Я пытаюсь использовать (clickoutside), чтобы закрыть панель (для параметра showEastPanel установлено значение false), однако открытая панель запускается сначала на угловом крючке, и для панели устанавливается значение true, затем false, и панель не отображается. Есть ли какой-нибудь способ "clickoutside", чтобы не включать кнопку?

<div [ngClass]="{'d-none': !showEastPanel, 'east-panel-container': showEastPanel}" (clickOutside)="ClosePanel()">
<div id="east-panel">
  <ng-template #eastPanel></ng-template>
</div>

<button (click)="ShowPanel()">Open Panel</button>

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Я бы сделал это, используя рекомендованный Angular подход, который также прост в разработке приложений в средах без доступа DOM, я имею в виду класс Renderer 2, который является абстракцией, предоставляемой Angular в форме сервис, который позволяет манипулировать элементами вашего приложения без непосредственного прикосновения к DOM.

В этом подходе вам нужно вставить Renderer2 в конструктор вашего компонента, который Renderer2 позволяет нам listen элегантно запускать события. Он просто принимает элемент, который вы собираетесь прослушивать, в качестве первого аргумента, который может быть window, document, body или любой другой ссылкой на элемент. Для второго аргумента требуется событие, которое мы собираемся прослушать, в данном случае это click, а третий аргумент на самом деле является функцией обратного вызова, которую мы делаем с помощью функции стрелки.

this.renderer.listen('window', 'click',(e:Event)=>{ // your code here})

Остальное решение простое, вам просто нужно установить логический флаг, который сохраняет статус видимости меню (или панели), и нам нужно назначить false этому флагу, когда он щелкает снаружи меню.

Вот ссылка на Stackblitz Demo

HTML

<button #toggleButton (click)="toggleMenu()"> Toggle Menu</button>

<div class="menu" *ngIf="isMenuOpen" #menu>
I'm the menu. Click outside to close me
</div>

app.component.ts

export class AppComponent {
  /**
   * This is the toogle button elemenbt, look at HTML and see its defination
   */
  @ViewChild('toggleButton') toggleButton: ElementRef;
  @ViewChild('menu') menu: ElementRef;

  constructor(private renderer: Renderer2) {
    /**
     * This events get called by all clicks on the page
     */
    this.renderer.listen('window', 'click',(e:Event)=>{
         /**
          * Only run when toggleButton is not clicked
          * If we don't check this, all clicks (even on the toggle button) gets into this
          * section which in the result we might never see the menu open!
          * And the menu itself is checked here, and it's where we check just outside of
          * the menu and button the condition abbove must close the menu
          */
        if(e.target !== this.toggleButton.nativeElement && e.target!==this.menu.nativeElement){
            this.isMenuOpen=false;
        }
    });
  }

  isMenuOpen = false;

  toggleMenu() {
    this.isMenuOpen = !this.isMenuOpen;
  }
}
0 голосов
/ 07 августа 2019

Я хотел бы добавить решение, которое помогло мне добиться правильного результата.

При использовании встроенных элементов, когда вы хотите обнаружить щелчок по родительскому элементу, в файле event.target указывается основной дочерний элемент.

HTML

<div #toggleButton (click)="toggleMenu()">
    <b>Toggle Menu</b>
    <span class="some-icon"></span>
</div>

<div #menu class="menu" *ngIf="isMenuOpen">
    <h1>I'm the menu.</h1>
    <div>
        I have some complex content containing multiple children.
        <i>Click outside to close me</i>
    </div>
</div>

Я нажимаю «Переключить меню» text, event.target возвращает ссылку на элемент 'u' вместо # toggleButton div.

Для этого случая я использовал решение M98, включая Renderer2, но изменил условие на то, что было в ответе Суджая.

ToggleButton.nativeElement.contains (e.target) возвращает true , даже если цель события click находится в дочерних элементах nativeElement, что решает проблему.

component.ts

export class AppComponent {
/**
 * This is the toogle button element, look at HTML and see its definition
 */
    @ViewChild('toggleButton') toggleButton: ElementRef;
    @ViewChild('menu') menu: ElementRef;
    isMenuOpen = false;

    constructor(private renderer: Renderer2) {
    /**
     * This events get called by all clicks on the page
     */
        this.renderer.listen('window', 'click',(e:Event)=>{
            /**
             * Only run when toggleButton is not clicked
             * If we don't check this, all clicks (even on the toggle button) gets into this
             * section which in the result we might never see the menu open!
             * And the menu itself is checked here, and it's where we check just outside of
             * the menu and button the condition abbove must close the menu
             */
            if(!this.toggleButton.nativeElement.contains(e.target) && !this.menu.nativeElement.contains(e.target)) {
                this.isMenuOpen=false;
            }
        });
    }

    toggleMenu() {
        this.isMenuOpen = !this.isMenuOpen;
    }
}
0 голосов
/ 03 июля 2018

вы можете сделать что-то вроде этого

  @HostListener('document:mousedown', ['$event'])
  onGlobalClick(event): void {
     if (!this.elementRef.nativeElement.contains(event.target)) {
        // clicked outside => close dropdown list
     this.isOpen = false;
     }
  }

и используйте * ngIf = isOpen для панели

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...