Tengo un menú desplegable de la siguiente manera, quiero cerrarlo cuando el usuario haga clic fuera del menú desplegable.
<div [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>He intentado con Angular2 Cerrar el menú desplegable al hacer clic afuera, ¿hay alguna manera más fácil? método pero no parece funcionar.
COMPORTAMIENTO ESPERADO: el menú desplegable debe estar cerrado.
COMPORTAMIENTO ACTUAL: Permanece abierto.
Creo que tienes dos opciones. El primero es hacer que el contenido div sea editable (o usar otro elemento que tenga un evento de desenfoque) y agregar un oyente para desdibujar el evento para ocultar el menú desplegable. El desenfoque se activará cuando el elemento pierda el foco, como hacer clic fuera, etc.
O puede agregar un detector de ventana a su componente y ocultarlo cuando haga clic fuera del menú desplegable como:
@Component({ selector: 'mySelector', template : 'YourTemplatehere', host: {'(window:mouseup)': 'handleMouseUp($event)'}, }) export class MyClass { handleMouseUp(e: MouseEvent) { // Your code to handle the hiding logic. I think in your case its; this.qtydropdownOpened = !this.qtydropdownOpened; } }<div> <button (click)="myFunction()" 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" #myDropdown> <ul class="default-dropdown"> <li *ngFor="let quantity of quantities"> <a (click)="qtydropdownOpened = !qtydropdownOpened;setQuantity(quantity)">{{quantity }}</a> </li> </ul> </div> </div>En su componente
@Component({ templateUrl: 'header.html' host: { '(document:click)': 'onClick($event)' } }) export class DropDownComponent{ @ViewChild('myDropdown') myDropdown: ElementRef; public myFunction() { this.myDropdown.nativeElement.classList.toggle("show") } // Close the dropdown if the user clicks outside of it onClick(event) { if (!event.target.matches('.dropbtn')) { var dropdowns = this.myDropdown.nativeElement; if (dropdowns.classList.contains('show')) { dropdowns.classList.remove('show'); } } } }Tuve el mismo problema cuando estaba haciendo un menú desplegable y un cuadro de diálogo de confirmación. Quería descartarlos al hacer clic fuera.
Mi implementación final funciona perfectamente pero requiere algunas animaciones y estilos css3.
NOTA : no he probado el siguiente código, puede haber algunos problemas de sintaxis que deben resolverse, ¡también los ajustes obvios para su propio proyecto!
Lo que hice:
Hice un div fijo separado con altura 100%, ancho 100% y transformación: escala (0), este es esencialmente el fondo, puede diseñarlo con color de fondo: rgba (0, 0, 0, 0.466); para que sea obvio que el menú está abierto y el fondo se cierra con un clic. El menú obtiene un índice z más alto que todo lo demás, luego el div de fondo obtiene un índice z más bajo que el menú pero también más alto que todo lo demás. Luego, el fondo tiene un evento de clic que cierra el menú desplegable.
Aquí está con su código 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>Aquí está el css3 que necesita algunas animaciones simples.
/* 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; } }Si no busca nada visual, puede usar una transición como esta
.dropdownbackground{ width: 100%; height: 100%; position: fixed; z-index: 2; transform: scale(0); opacity: 0; transition all 0.1s; } .dropdownbackground.showbackground{ transform: scale(1); }