Я хотел бы закрыть раскрывающееся меню входа в систему, когда пользователь щелкает где-нибудь за пределами этого раскрывающегося списка, и я хотел бы сделать это с помощью Angular2 и с "подходом" Angular2 ...
Я реализовал решение, но я действительно не уверен в нем. Я думаю, что должен быть самый простой способ добиться того же результата, так что если у вас есть идеи ... давайте обсудим :)!
Вот моя реализация:
Выпадающий компонент:
Это компонент моего раскрывающегося списка:
- Каждый раз , когда этот компонент он установлен в видимой (Например: когда пользователь нажимает на кнопку , чтобы отобразить его) это подписаться на «глобальный» rxjs предмет UserMenu хранится в SubjectsService .
- И каждый раз, когда его прячут, он отписывается в этой теме.
- Каждый щелчок в любом месте в пределах шаблона этого компонента триггера OnClick () метод, который просто остановка событие барботирования в верхней части (и компонент приложения)
Вот код
export class UserMenuComponent {
_isVisible: boolean = false;
_subscriptions: Subscription<any> = null;
constructor(public subjects: SubjectsService) {
}
onClick(event) {
event.stopPropagation();
}
set isVisible(v) {
if( v ){
setTimeout( () => {
this._subscriptions = this.subjects.userMenu.subscribe((e) => {
this.isVisible = false;
})
}, 0);
} else {
this._subscriptions.unsubscribe();
}
this._isVisible = v;
}
get isVisible() {
return this._isVisible;
}
}
Компонент приложения:
С другой стороны, есть компонент приложения (который является родителем раскрывающегося компонента):
- Этот компонент улавливает каждое событие щелчка и генерирует один и тот же объект rxjs ( userMenu )
Вот код:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
Что меня беспокоит:
- Мне не очень нравится идея иметь глобальный субъект, который действует как связующее звено между этими компонентами.
- SetTimeout : Это необходимо , потому что здесь это то , что произойдет в противном случае , если пользователь нажимает на кнопку , которая показывает выпадающее меню:
- Пользователь нажимает кнопку (которая не является частью раскрывающегося списка), чтобы отобразить раскрывающийся список.
- Отображается раскрывающийся список, и он сразу же подписывается на тему userMenu .
- Пузырь события клика поднимается до компонента приложения и ловится
- Компонент приложения генерирует событие для темы userMenu
- Компонент раскрывающегося списка улавливает это действие в userMenu и скрывает раскрывающийся список.
- В конце раскрывающийся список никогда не отображается.
Этот установленный тайм-аут задерживает подписку до конца текущей очереди кода JavaScript, что решает проблему, но, на мой взгляд, очень элегантно.
Если вы знаете более чистые, лучшие, умные, быстрые или сильные решения, дайте мне знать :)!
источник
Ответы:
Вы можете использовать
(document:click)
событие:@Component({ host: { '(document:click)': 'onClick($event)', }, }) class SomeComponent() { constructor(private _eref: ElementRef) { } onClick(event) { if (!this._eref.nativeElement.contains(event.target)) // or some similar check doSomething(); } }
Другой подход - создать настраиваемое событие в виде директивы. Посмотрите эти сообщения Бена Наделя:
источник
@HostListener('document:click', ['$event'])
вместоhost
свойства вComponent
декораторе.Observable.fromEvent(document, 'click').subscribe(event => {your code here})
, чтобы вы всегда могли подписаться только тогда, когда вам нужно слушать, например, вы открыли раскрывающийся список, а когда вы его закрываете, выЭЛЕГАНТНЫЙ МЕТОД
Я нашел эту
clickOut
директиву: https://github.com/chliebel/angular2-click-outside . Проверяю, работает хорошо (копирую толькоclickOutside.directive.ts
в свой проект). Вы можете использовать это так:<div (clickOutside)="close($event)"></div>
Где
close
находится ваша функция, которая будет вызываться, когда пользователь щелкнет за пределами div. Это очень элегантный способ решения описанной проблемы.Если вы используете указанную выше директиву для закрытия всплывающего окна, не забудьте сначала добавить
event.stopPropagation()
в обработчик события нажатия кнопки, который открывает всплывающее окно.БОНУС:
Ниже я копирую исходный код директивы из файла
clickOutside.directive.ts
(на случай, если ссылка перестанет работать в будущем) - автор Кристиан Либель :Показать фрагмент кода
import {Directive, ElementRef, Output, EventEmitter, HostListener} from '@angular/core'; @Directive({ selector: '[clickOutside]' }) export class ClickOutsideDirective { constructor(private _elementRef: ElementRef) { } @Output() public clickOutside = new EventEmitter<MouseEvent>(); @HostListener('document:click', ['$event', '$event.target']) public onClick(event: MouseEvent, targetElement: HTMLElement): void { if (!targetElement) { return; } const clickedInside = this._elementRef.nativeElement.contains(targetElement); if (!clickedInside) { this.clickOutside.emit(event); } } }
источник
<div class="wrap" *ngIf="isOpened" (clickOutside)="...// this should set this.isOpen=false"
Я так и сделал.
Добавил прослушиватель событий в документ
click
и в этом обработчике проверил,container
содержит ли мойevent.target
, если нет - скрыть раскрывающийся список.Это выглядело бы так.
@Component({}) class SomeComponent { @ViewChild('container') container; @ViewChild('dropdown') dropdown; constructor() { document.addEventListener('click', this.offClickHandler.bind(this)); // bind on doc } offClickHandler(event:any) { if (!this.container.nativeElement.contains(event.target)) { // check click origin this.dropdown.nativeElement.style.display = "none"; } } }
источник
this.offClickHandler
заключил в функцию стрелки.Я думаю, что принятый ответ Sasxa работает для большинства людей. Однако у меня была ситуация, когда содержимое элемента, который должен прослушивать события вне щелчка, изменялся динамически. Таким образом, Elements nativeElement не содержал event.target, когда он создавался динамически. Я мог бы решить эту проблему с помощью следующей директивы
@Directive({ selector: '[myOffClick]' }) export class MyOffClickDirective { @Output() offClick = new EventEmitter(); constructor(private _elementRef: ElementRef) { } @HostListener('document:click', ['$event.path']) public onGlobalClick(targetElementPath: Array<any>) { let elementRefInPath = targetElementPath.find(e => e === this._elementRef.nativeElement); if (!elementRefInPath) { this.offClick.emit(null); } } }
Вместо того, чтобы проверять, содержит ли elementRef event.target, я проверяю, находится ли elementRef в пути (путь DOM к цели) события. Таким образом можно обрабатывать динамически созданные элементы.
источник
Если вы делаете это на iOS, также используйте
touchstart
событие:Начиная с Angular 4,
HostListener
украшение является предпочтительным способом сделать это.import { Component, OnInit, HostListener, ElementRef } from '@angular/core'; ... @Component({...}) export class MyComponent implement OnInit { constructor(private eRef: ElementRef){} @HostListener('document:click', ['$event']) @HostListener('document:touchstart', ['$event']) handleOutsideClick(event) { // Some kind of logic to exclude clicks in Component. // This example is borrowed Kamil's answer if (!this.eRef.nativeElement.contains(event.target) { doSomethingCool(); } } }
источник
Сегодня мы работаем над аналогичной проблемой, пытаясь выяснить, как заставить выпадающий div исчезать при нажатии на него. Наш вопрос немного отличается от вопроса первоначального постера, потому что мы не хотели уходить от другого компонента или директивы , а просто за пределами конкретного div.
В итоге мы решили ее с помощью обработчика событий (window: mouseup).
Шаги:
1.) Мы дали всему раскрывающемуся меню div уникальное имя класса.
2.) В самом внутреннем раскрывающемся меню (единственной части, в которой мы хотели, чтобы щелчки НЕ закрывали меню), мы добавили обработчик событий (window: mouseup) и передали в событие $.
ПРИМЕЧАНИЕ. Это невозможно сделать с помощью обычного обработчика щелчка, поскольку он конфликтует с родительским обработчиком щелчка.
3.) В нашем контроллере мы создали метод, который должен вызываться при событии щелчка мышью, и мы используем event.closest ( здесь документы ), чтобы узнать, находится ли место, на которое щелкнули, в пределах нашего div целевого класса.
autoCloseForDropdownCars(event) { var target = event.target; if (!target.closest(".DropdownCars")) { // do whatever you want here } }
<div class="DropdownCars"> <span (click)="toggleDropdown(dropdownTypes.Cars)" class="searchBarPlaceholder">Cars</span> <div class="criteriaDropdown" (window:mouseup)="autoCloseForDropdownCars($event)" *ngIf="isDropdownShown(dropdownTypes.Cars)"> </div> </div>
источник
.closest()
на сегодняшний день не поддерживается в IE / Edge ( caniuse )Вы можете создать элемент-брат для раскрывающегося списка, охватывающий весь экран, который будет невидимым и будет использоваться только для захвата событий щелчка. Затем вы можете обнаруживать щелчки по этому элементу и закрывать раскрывающийся список при щелчке по нему. Допустим, этот элемент относится к классу шелкографии, вот какой стиль для него:
.silkscreen { position: fixed; top: 0; bottom: 0; left: 0; right: 0; z-index: 1; }
Z-index должен быть достаточно высоким, чтобы размещать его над всем, кроме раскрывающегося списка. В этом случае мое раскрывающееся меню будет b z-index 2.
Другие ответы в некоторых случаях работали для меня, за исключением случаев, когда мой раскрывающийся список закрывался, когда я взаимодействовал с элементами внутри него, а я этого не хотел. У меня были динамически добавленные элементы, которые не содержались в моем компоненте, в соответствии с целью события, как я и ожидал. Я решил, что вместо того, чтобы разбираться с этим беспорядком, просто попробую сделать это методом шелкографии.
источник
Я не нашел обходного пути. Я только что прикрепил документ: нажмите на мою функцию переключения, как показано ниже:
Итак, когда я выхожу за пределы своей директивы, я закрываю раскрывающийся список.
источник
import { Component, HostListener } from '@angular/core'; @Component({ selector: 'custom-dropdown', template: ` <div class="custom-dropdown-container"> Dropdown code here </div> ` }) export class CustomDropdownComponent { thisElementClicked: boolean = false; constructor() { } @HostListener('click', ['$event']) onLocalClick(event: Event) { this.thisElementClicked = true; } @HostListener('document:click', ['$event']) onClick(event: Event) { if (!this.thisElementClicked) { //click was outside the element, do stuff } this.thisElementClicked = false; } }
СНИЖЕНИЯ: - Два прослушивателя событий щелчка для каждого из этих компонентов на странице. Не используйте это для компонентов, которые появляются на странице сотни раз.
источник
Я хотел бы дополнить ответ @Tony, поскольку событие не удаляется после щелчка за пределами компонента. Полная квитанция:
Отметьте свой основной элемент с помощью #container
@ViewChild('container') container; _dropstatus: boolean = false; get dropstatus() { return this._dropstatus; } set dropstatus(b: boolean) { if (b) { document.addEventListener('click', this.offclickevent);} else { document.removeEventListener('click', this.offclickevent);} this._dropstatus = b; } offclickevent: any = ((evt:any) => { if (!this.container.nativeElement.contains(evt.target)) this.dropstatus= false; }).bind(this);
На интерактивном элементе используйте:
(click)="dropstatus=true"
Теперь вы можете контролировать свое раскрывающееся состояние с помощью переменной dropstatus и применять соответствующие классы с помощью [ngClass] ...
источник
Вы можете написать директиву:
@Directive({ selector: '[clickOut]' }) export class ClickOutDirective implements AfterViewInit { @Input() clickOut: boolean; @Output() clickOutEvent: EventEmitter<any> = new EventEmitter<any>(); @HostListener('document:mousedown', ['$event']) onMouseDown(event: MouseEvent) { if (this.clickOut && !event.path.includes(this._element.nativeElement)) { this.clickOutEvent.emit(); } } }
В вашем компоненте:
@Component({ selector: 'app-root', template: ` <h1 *ngIf="isVisible" [clickOut]="true" (clickOutEvent)="onToggle()" >{{title}}</h1> `, styleUrls: ['./app.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class AppComponent { title = 'app works!'; isVisible = false; onToggle() { this.isVisible = !this.isVisible; } }
Эта директива генерирует событие, когда элемент html содержится в DOM и когда свойство input [clickOut] имеет значение «true». Он прослушивает событие mousedown для обработки события до того, как элемент будет удален из DOM.
И одно примечание: firefox не содержит свойство path, если вы можете использовать функцию для создания пути:
const getEventPath = (event: Event): HTMLElement[] => { if (event['path']) { return event['path']; } if (event['composedPath']) { return event['composedPath'](); } const path = []; let node = <HTMLElement>event.target; do { path.push(node); } while (node = node.parentElement); return path; };
Поэтому вам следует изменить обработчик событий в директиве: event.path следует заменить getEventPath (event)
Этот модуль может помочь. https://www.npmjs.com/package/ngx-clickout Он содержит ту же логику, но также обрабатывает событие esc в исходном элементе html.
источник
При правильном ответе есть проблема: если у вас есть компонент clicakble в вашем всплывающем окне, элемент больше не будет использоваться в
contain
методе и закроется, на основе @ JuHarm89 я создал свой собственный:export class PopOverComponent implements AfterViewInit { private parentNode: any; constructor( private _element: ElementRef ) { } ngAfterViewInit(): void { this.parentNode = this._element.nativeElement.parentNode; } @HostListener('document:click', ['$event.path']) onClickOutside($event: Array<any>) { const elementRefInPath = $event.find(node => node === this.parentNode); if (!elementRefInPath) { this.closeEventEmmit.emit(); } } }
Спасибо за помощь!
источник
Лучшая версия для отличного решения @Tony:
@Component({}) class SomeComponent { @ViewChild('container') container; @ViewChild('dropdown') dropdown; constructor() { document.addEventListener('click', this.offClickHandler.bind(this)); // bind on doc } offClickHandler(event:any) { if (!this.container.nativeElement.contains(event.target)) { // check click origin this.dropdown.nativeElement.closest(".ourDropdown.open").classList.remove("open"); } } }
В файле css: // НЕ требуется, если вы используете раскрывающийся список начальной загрузки.
.ourDropdown{ display: none; } .ourDropdown.open{ display: inherit; }
источник
Вы должны проверить, нажимаете ли вы вместо этого модальное наложение, намного проще.
Ваш шаблон:
<div #modalOverlay (click)="clickOutside($event)" class="modal fade show" role="dialog" style="display: block;"> <div class="modal-dialog" [ngClass]='size' role="document"> <div class="modal-content" id="modal-content"> <div class="close-modal" (click)="closeModal()"> <i class="fa fa-times" aria-hidden="true"></i></div> <ng-content></ng-content> </div> </div> </div>
И способ:
@ViewChild('modalOverlay') modalOverlay: ElementRef; // ... your constructor and other method clickOutside(event: Event) { const target = event.target || event.srcElement; console.log('click', target); console.log("outside???", this.modalOverlay.nativeElement == event.target) // const isClickOutside = !this.modalBody.nativeElement.contains(event.target); // console.log("click outside ?", isClickOutside); if ("isClickOutside") { // this.closeModal(); } }
источник
Если вы используете Bootstrap, вы можете сделать это напрямую с помощью способа начальной загрузки через раскрывающиеся списки (компонент Bootstrap).
<div class="input-group"> <div class="input-group-btn"> <button aria-expanded="false" aria-haspopup="true" class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button"> Toggle Drop Down. <span class="fa fa-sort-alpha-asc"></span> </button> <ul class="dropdown-menu"> <li>List 1</li> <li>List 2</li> <li>List 3</li> </ul> </div> </div>
Теперь можно положить что-
(click)="clickButton()"
нибудь на кнопку. http://getbootstrap.com/javascript/#dropdownsисточник
Я также сделал небольшое собственное обходное решение.
Я создал событие (dropdownOpen), которое я прослушиваю в своем компоненте элемента ng-select, и вызываю функцию, которая закроет все другие открытые компоненты SelectComponent, кроме открытого в данный момент SelectComponent.
Я изменил одну функцию внутри файла select.ts, как показано ниже, чтобы генерировать событие:
private open():void { this.options = this.itemObjects .filter((option:SelectItem) => (this.multiple === false || this.multiple === true && !this.active.find((o:SelectItem) => option.text === o.text))); if (this.options.length > 0) { this.behavior.first(); } this.optionsOpened = true; this.dropdownOpened.emit(true); }
В HTML я добавил прослушиватель событий для (dropdownOpened) :
<ng-select #elem (dropdownOpened)="closeOtherElems(elem)" [multiple]="true" [items]="items" [disabled]="disabled" [isInputAllowed]="true" (data)="refreshValue($event)" (selected)="selected($event)" (removed)="removed($event)" placeholder="No city selected"></ng-select>
Это моя вызывающая функция для триггера события внутри компонента, имеющего тег ng2-select:
@ViewChildren(SelectComponent) selectElem :QueryList<SelectComponent>; public closeOtherElems(element){ let a = this.selectElem.filter(function(el){ return (el != element) }); a.forEach(function(e:SelectComponent){ e.closeDropdown(); }) }
источник
НОТА: Для тех, кто хочет использовать веб-воркеров, и вам нужно избегать использования document и nativeElement, это сработает.
Я ответил на тот же вопрос здесь: /programming/47571144
Скопируйте / Вставьте из приведенной выше ссылки:
У меня была такая же проблема, когда я создавал раскрывающееся меню и диалоговое окно подтверждения, которое я хотел отклонить при нажатии снаружи.
Моя последняя реализация работает отлично, но требует некоторой анимации и стиля css3.
ПРИМЕЧАНИЕ : я не тестировал приведенный ниже код, могут быть некоторые проблемы с синтаксисом, которые необходимо устранить, а также очевидные корректировки для вашего собственного проекта!
Что я сделал:
Я сделал отдельный фиксированный div с высотой 100%, шириной 100% и transform: scale (0), это, по сути, фон, вы можете стилизовать его с помощью background-color: rgba (0, 0, 0, 0.466); чтобы было видно, что меню открыто, а фон закрывается щелчком. Меню получает z-индекс выше, чем все остальное, тогда фоновый div получает z-индекс ниже, чем у меню, но также выше, чем все остальное. Затем на фоне появляется событие щелчка, закрывающее раскрывающийся список.
Вот он с вашим html-кодом.
<div class="dropdownbackground" [ngClass]="{showbackground: qtydropdownOpened}" (click)="qtydropdownOpened = !qtydropdownOpened"><div> <div class="zindex" [class.open]="qtydropdownOpened"> <button (click)="qtydropdownOpened = !qtydropdownOpened" type="button" data-toggle="dropdown" aria-haspopup="true" [attr.aria-expanded]="qtydropdownOpened ? 'true': 'false' "> {{selectedqty}}<span class="caret margin-left-1x "></span> </button> <div class="dropdown-wrp dropdown-menu"> <ul class="default-dropdown"> <li *ngFor="let quantity of quantities"> <a (click)="qtydropdownOpened = !qtydropdownOpened;setQuantity(quantity)">{{quantity }}</a> </li> </ul> </div> </div>
Вот CSS3, для которого нужны простые анимации.
/* make sure the menu/drop-down is in front of the background */ .zindex{ z-index: 3; } /* make background fill the whole page but sit behind the drop-down, then scale it to 0 so its essentially gone from the page */ .dropdownbackground{ width: 100%; height: 100%; position: fixed; z-index: 2; transform: scale(0); opacity: 0; background-color: rgba(0, 0, 0, 0.466); } /* this is the class we add in the template when the drop down is opened it has the animation rules set these how you like */ .showbackground{ animation: showBackGround 0.4s 1 forwards; } /* this animates the background to fill the page if you don't want any thing visual you could use a transition instead */ @keyframes showBackGround { 1%{ transform: scale(1); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
Если вам не нужно ничего визуального, вы можете просто использовать такой переход
.dropdownbackground{ width: 100%; height: 100%; position: fixed; z-index: 2; transform: scale(0); opacity: 0; transition all 0.1s; } .dropdownbackground.showbackground{ transform: scale(1); }
источник
Я сделал директиву для решения этой похожей проблемы и использую Bootstrap. Но в моем случае, вместо того, чтобы ждать события щелчка вне элемента, чтобы закрыть текущее открытое раскрывающееся меню, я думаю, что лучше, если мы будем следить за событием mouseleave, чтобы автоматически закрыть меню.
Вот мое решение:
Директива
import { Directive, HostListener, HostBinding } from '@angular/core'; @Directive({ selector: '[appDropdown]' }) export class DropdownDirective { @HostBinding('class.open') isOpen = false; @HostListener('click') toggleOpen() { this.isOpen = !this.isOpen; } @HostListener('mouseleave') closeDropdown() { this.isOpen = false; } }
HTML
<ul class="nav navbar-nav navbar-right"> <li class="dropdown" appDropdown> <a class="dropdown-toggle" data-toggle="dropdown">Test <span class="caret"></span> </a> <ul class="dropdown-menu"> <li routerLinkActive="active"><a routerLink="/test1">Test1</a></li> <li routerLinkActive="active"><a routerLink="/test2/">Test2</a></li> </ul> </li> </ul>
источник
Я наткнулся на другое решение, вдохновленное примерами с событием focus / blur.
Итак, если вы хотите достичь той же функциональности без подключения глобального прослушивателя документов, вы можете считать допустимым следующий пример. Он также работает в Safari и Firefox на OSx, несмотря на то, что у них есть другая обработка события фокусировки кнопки: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus
Рабочий пример на stackbiz с angular 8: https://stackblitz.com/edit/angular-sv4tbi?file=src%2Ftoggle-dropdown%2Ftoggle-dropdown.directive.ts
Разметка HTML:
<div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" aria-haspopup="true" aria-expanded="false">Dropdown button</button> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <a class="dropdown-item" href="#">Action</a> <a class="dropdown-item" href="#">Another action</a> <a class="dropdown-item" href="#">Something else here</a> </div> </div>
Директива будет выглядеть так:
import { Directive, HostBinding, ElementRef, OnDestroy, Renderer2 } from '@angular/core'; @Directive({ selector: '.dropdown' }) export class ToggleDropdownDirective { @HostBinding('class.show') public isOpen: boolean; private buttonMousedown: () => void; private buttonBlur: () => void; private navMousedown: () => void; private navClick: () => void; constructor(private element: ElementRef, private renderer: Renderer2) { } ngAfterViewInit() { const el = this.element.nativeElement; const btnElem = el.querySelector('.dropdown-toggle'); const menuElem = el.querySelector('.dropdown-menu'); this.buttonMousedown = this.renderer.listen(btnElem, 'mousedown', (evt) => { console.log('MOUSEDOWN BTN'); this.isOpen = !this.isOpen; evt.preventDefault(); // prevents loose of focus (default behaviour) on some browsers }); this.buttonMousedown = this.renderer.listen(btnElem, 'click', () => { console.log('CLICK BTN'); // firefox OSx, Safari, Ie OSx, Mobile browsers. // Whether clicking on a <button> causes it to become focused varies by browser and OS. btnElem.focus(); }); // only for debug this.buttonMousedown = this.renderer.listen(btnElem, 'focus', () => { console.log('FOCUS BTN'); }); this.buttonBlur = this.renderer.listen(btnElem, 'blur', () => { console.log('BLUR BTN'); this.isOpen = false; }); this.navMousedown = this.renderer.listen(menuElem, 'mousedown', (evt) => { console.log('MOUSEDOWN MENU'); evt.preventDefault(); // prevents nav element to get focus and button blur event to fire too early }); this.navClick = this.renderer.listen(menuElem, 'click', () => { console.log('CLICK MENU'); this.isOpen = false; btnElem.blur(); }); } ngOnDestroy() { this.buttonMousedown(); this.buttonBlur(); this.navMousedown(); this.navClick(); } }
источник
Вы можете использовать
mouseleave
в своем представлении вот такПротестируйте с angular 8 и отлично работайте
<ul (mouseleave)="closeDropdown()"> </ul>
источник
САМЫЙ ЭЛЕГАНТНЫЙ МЕТОД: D
Есть один самый простой способ сделать это, для этого не нужны никакие директивы.
"element-that-toggle-your-dropdown" должен быть тегом кнопки. Используйте любой метод в атрибуте (blur). Вот и все.
<button class="element-that-toggle-your-dropdown" (blur)="isDropdownOpen = false" (click)="isDropdownOpen = !isDropdownOpen"> </button>
источник