Обнаружение щелчка за пределами элемента Angular 9 - несколько экземпляров

В моем приложении при щелчке элемента я показываю всплывающую подсказку, содержащую дополнительную информацию. Это доступно для всех элементов в списке. Я хотел бы иметь возможность закрывать расширение, щелкнув что-либо за пределами всплывающей подсказки.

По сути, концепция - это то, что рассматривается в этом вопросе, но мне нужно, чтобы она работала, если существует несколько экземпляров элемента. Я попытался использовать ViewChildren для элементов, а не ViewChild, поскольку их несколько, но это не дает того, что я ищу. Я бы не хотел использовать какие-либо пакеты, которые еще не доступны из@angular/core, rxjsи т.д., если возможно. См. Ниже упрощенную и сжатую версию того, что я пытался пока безуспешно.

HTML

<li *ngFor="let listItem of listItems;">
  <p>
    <span *ngIf="showTooltip" class="item-tooltip" #itemTooltip>
      Tooltip with {{ listItem.detailed }}
      <span (click)="toggleTooltip()">Close</span>
    </span>
    <span (click)="toggleTooltip()" #tooltipTrigger>{{ listItem.blurb }}</span>
  </p>
</li>

TS

@ViewChildren('itemTooltip') itemTooltip: ElementRef;
@ViewChildren('tooltipTrigger') tooltipTrigger: ElementRef;
this.showTooltip = false;

constructor( private renderer: Renderer2) {
  this.renderer.listen('window', 'click', (e: Event) => {
    if (this.showTooltip && e.target !== this.itemTooltip.nativeElement) {
      // never gets to here 
      console.log(‘click detected’);
      this.toggleTooltip();
    }
  });
}

toggleTooltip() {
  const tooltipStatus = this.showTooltip;
  if (tooltipStatus = true) {
    this.showTooltip = false;
  } else if (tooltipStatus = false) {
    this.showTooltip = true;
  }
}

1 ответ

Создайте директиву в общем месте для доступа из любого места, добавьте ее в модуль также для использованиядирективы

import {Directive, ElementRef, Output, EventEmitter, HostListener} from '@angular/core';
 
@Directive({
    selector: '[clickOutside]'
})
export class ClickOutsideDirective {
    constructor(private _elementRef : ElementRef) {
    }
 
    @Output()
    public clickOutside = new EventEmitter();
 
    @HostListener('document:click', ['$event.target'])
    public onClick(targetElement) {
        const clickedInside = this._elementRef.nativeElement.contains(targetElement);
        if (!clickedInside) {
            this.clickOutside.emit(null);
        }
    }
}

HTML

<li *ngFor="let listItem of listItems;">
  <p>
    <span *ngIf="showTooltip" class="item-tooltip" #itemTooltip>
      Tooltip with {{ listItem.detailed }}
      <span (clickOutside )="closeTooltip()">Close</span>
    </span>
    <span (click)="openTooltip()" #tooltipTrigger>{{ listItem.blurb }}</span>
  </p>
</li>

TS

openTooltip = () => { showTooltip = true; }

clickOutside = () => { showTooltip = false; }
Другие вопросы по тегам