Как я могу закрыть карту по клику вне ее в Angular?

avatar
hanushic
8 августа 2021 в 17:00
297
2
0

Я создал контекстное меню.

Это мой html:

<nb-user  (click)="openMenuBar()" [onlyPicture]="userPictureOnly" [name]="user?.userName">
</nb-user>

<nb-card class="context-menu" >
  <nb-menu *ngIf="menuOpened"  [items]="userMenu" autoCollapse="true">
  </nb-menu> 
</nb-card>

.ts

menuOpened = false;

openMenuBar() {
    this.menuOpened = !this.menuOpened;
    if (this.menuOpened === true) {
        (<HTMLElement>document.querySelector('nb-layout-column')).style.filter = 'blur(10px)';
    } else {
        (<HTMLElement>document.querySelector('nb-layout-column')).style.filter = 'unset';
    }
}

Я также размыл фон. Проблема в том, что когда я нажимаю на фон nb-card (menu-bar), другие кнопки на фоне также активны.

Что я хочу сделать: когда я щелкаю за пределами карточки меню, карточка (menu-bar) должна закрываться.

Как я могу это сделать?

Источник
programoholic
8 августа 2021 в 18:31
0

проведите stackblitz, чтобы мы могли вам помочь.

hanushic
9 августа 2021 в 01:37
0

@programoholic stackblitz.com/edit/…. Помоги мне

programoholic
9 августа 2021 в 09:08
0

ты смог ее решить?

programoholic
9 августа 2021 в 09:58
0

проверьте мой ответ.

Ответы (2)

avatar
programoholic
9 августа 2021 в 09:58
0

Вы можете сделать это, используя Renderer2. Подробнее об этом читайте на Здесь

Внесите следующие изменения:

  • импортировать следующие пакеты:

       import { Component,Renderer2, ElementRef, ViewChild } from '@angular/core';
    
  • Зарегистрируйте метод click в конструкторе следующим образом:

    constructor(private _renderer: Renderer2) {
    
     this._renderer.listen('window', 'click', (e: Event) => {
       /**
        * This events get called by all clicks on the page
        */
    
       /**
        * This conditon will prevent execution when you click on button
        * If we don't check this, all clicks (even on the toggle button) gets into
        */
       if (
         e.target !== this.toggleButton.nativeElement &&
         e.target !== this.menu.nativeElement
       ) {
         this.menuOpened = false;
       }
     });}
    
  • Этот метод будет прослушивать каждое событие клика на странице. Теперь вам нужно добавить селекторы в HTML :

     <button (click)="openMenuBar()"  #toggleButton> click me</button>
    
      <div class="context-menu">
        <div *ngIf="menuOpened" #menu>
          This should disappear when i click outside of the click-me button
        </div>
      </div>
    

    Вот оно. Теперь ваш компонент будет прослушивать события щелчка, и если источником не является кнопка или сама карточка, он установит значение menuOpened в false.

    .

Вот демонстрация

avatar
Chris W
8 августа 2021 в 19:24
0

Я сделал нечто подобное с пользовательской директивой.

Создайте новый файл со следующим:

import { Directive, ElementRef, EventEmitter, HostListener, Output } from '@angular/core';

@Directive({selector: '[clickElsewhere]'})
export class ClickElsewhereDirective {

  @Output()
  clickElsewhere = new EventEmitter<MouseEvent>();

  constructor(private elementRef: ElementRef) {}

  @HostListener('document:click', ['$event'])
  public onDocumentClick(event: MouseEvent) {
    const targetElement = event.target as HTMLElement;

    if (targetElement && !this.elementRef.nativeElement.contains(targetElement)) {
      this.clickElsewhere.emit(event);
    }
  }
}

Затем в файле module.ts добавьте ClickElsewhereDirective к вашим объявлениям.

Затем добавьте директиву в меню:

  <nb-card class="context-menu" >
        <nb-menu
            (clickElsewhere)="closeMenuBar()" 
            *ngIf="menuOpened"  [items]="userMenu" autoCollapse="true"
        >
        </nb-menu> 
      </nb-card>

Наконец, добавьте функцию closeMenuBar(), чтобы установить для menuOpened значение false и все остальное, что вы хотите.

Эта директива работает следующим образом: прослушивает любые события кликов, которые происходят за пределами компонента, к которому она применяется, например, за пределами вашего меню, а затем генерирует событие, которое вы привязываете к функции закрытия меню.

hanushic
9 августа 2021 в 01:09
0

@Directive({selector: '[clickElsewhere]'}) это дает мне ошибку. Я уже добавил свое имя класса в объявления module.ts, которые я поставил так: @Directive({selector: '[clickElsewhere]'}) @Component({ selector: "ngx-header", styleUrls: ["./header.component.scss"], templateUrl: "./header.component.html", }) export class HeaderComponent implements OnInit, OnDestroy {

hanushic
9 августа 2021 в 01:13
0

Ошибка The class 'HeaderComponent' is listed in the declarations of the NgModule 'ThemeModule', but is not a directive, a component, or a pipe. Either remove it from the NgModule's declarations, or add an appropriate Angular decorator.