2
votes

Comment ouvrir la liste déroulante en survol avec angular au lieu de jquery?

Je voudrais remplacer l'instruction jquery suivante dans mon côté client par angular (7.x):

   //element-wise angular code
<li #drop class="dropdown singleDro" (mouseover)="openDropDown($event)" (mouseleave)="closeDropDown($event)">
            <a href="javascript:void(0)"
               class="dropdown-toggle"
               data-toggle="dropdown"
               role="button"
               aria-haspopup="true"
               aria-expanded="false">
              <i class="fa fa-list-ul icon-dash" aria-hidden="true"></i> Listings <i class="fa fa-angle-down" aria-hidden="true"></i></a>
            <ul class="dropdown-menu">
              <li><a [routerLink]="['/dashboard/shop/add']">Add Shop</a></li>
              <li><a [routerLink]="['/dashboard/shop/view']">My Shops</a></li>
            </ul>
          </li>


//component code
  openDropDown(event: Event) {
    if (this.navbarDash.nativeElement.offsetWidth > 1007) {
      this.renderer.addClass(this.drop.nativeElement, 'open');
    }
  }
  closeDropDown(event: Event) {
    this.renderer.removeClass(this.drop.nativeElement, 'open');
  }

À présent, j'ai provisoirement utilisé ElementRef et Renderer2 avec correspondant (mouse .. .) - Auditeurs d'événements. Je pourrais aussi déplacer cette logique vers une directive avec un Hostlistener ...

   //dropdown on hover in jquery

if($('.navbar').width() > 1007)
  {
    $('.nav .dropdown').hover(function() {
      $(this).addClass('open');
    },
    function() {
      $(this).removeClass('open');
    });
  }

... mais je recherche une solution plus holistique, qui a un effet similaire comme le solution jquery. Je préférerais une solution au niveau de l'application qui puisse être propagée à tous les enfants ...

Pourriez-vous s'il vous plaît me donner un indice sur le concept qui pourrait aider à réaliser ce qui est décrit. p>

Merci

Hucho


0 commentaires

3 Réponses :


0
votes

Vous pouvez utiliser ngClass ou class.open comme suit

  isDropdownOpen = false;

  ...

  openDropDown(event: Event) {
    if (this.navbarDash.nativeElement.offsetWidth > 1007) {
      this.isDropdownOpen = true;
    }
  }
  closeDropDown(event: Event) {
    this.isDropdownOpen = false;
  }

ou

<li #drop class="dropdown singleDro" 
[ngClass]="{ 'open': isDropdownOpen}"
(mouseover)="openDropDown($event)" 
(mouseleave)="closeDropDown($event)">...dropdown-stuff..</li>


0 commentaires

1
votes

Vous pouvez simplement utiliser NgClass , lorsque mouseover est déclenché, vous pouvez simplement mettre un booléen à true.

Quelque chose comme ça:

<li #drop 
class="dropdown singleDro" 
(mouseover)="isOpened = true" 
(mouseleave)="isOpened = false" 
ngClass="isOpened ? 'open' : ''">...dropdown-stuff..</li> 


5 commentaires

Merci à vous deux pour les astuces qui fonctionnent évidemment et sont des raccourcis de ma solution..le code jquery a cependant un effet sur tout le dom. Ce code n'effectue qu'une seule balise et je dois l'insérer manuellement dans toutes les listes déroulantes ... Que peut-on faire pour effectuer toutes les listes déroulantes au niveau de l'application et de ses enfants?


La solution la plus intelligente est de créer un composant qui fait cela. Ou vous pouvez résumer votre classe, mais vous devez enregistrer chaque liste déroulante.


Un composant ou une directive? Quel serait le concept de ce composant?


Vous pouvez créer une directive, mais je ne sais pas en quoi votre logique est difficile dans cette liste déroulante. Vous pouvez donc choisir la meilleure approche


Je pense que la directive est la meilleure solution dans ce cas. C'est une mauvaise chose de correspondre fortement à une logique de ce type pour une barre de navigation. Angular est connu pour éviter un tel couplage de cette manière



0
votes

Enfin, cela a fonctionné:

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

@Directive({
  selector: '[appDropOpen]'
})
export class DropOpenDirective {

  constructor(private el: ElementRef, private renderer: Renderer2) { }

  @HostListener('mouseover') onMouseOver() {
      const elementCollection = document.getElementsByClassName('navbar');
    if (elementCollection[0].clientWidth > 1007) {
    this.renderer.addClass(this.el.nativeElement, 'open');
    }
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.renderer.removeClass(this.el.nativeElement, 'open');
  }
}


0 commentaires