How can one click the button within the expanded dropdown while hovering over the navigation item in Angular and Bootstrap?

Issue Description: Upon hovering over a navigation item, the dropdown container is displayed but it's not clickable.

Desired Behavior: Hovering over a navigation item should display the dropdown container and allow clicking on its contents. Furthermore, when moving away from the navigation item and dropdown container, the container should be hidden.

To access the StackBlitz code example, click on this link

HTML:

 <div class="flex-container">
  <div *ngFor="let item of navigations">
    <ng-container *ngIf="item.type == 'dropdown'">
      <div
        class="dropdown p-0"
        (mouseenter)="showDropdown(item)"
        (mouseleave)="hideDropdown(item)"
      >
        <a
          class="cs-link-white dropdown-toggle"
          href="#"
          role="button"
          data-bs-toggle="dropdown"
          aria-expanded="false"
        >
          {{ item.menuTitle }}
        </a>
      </div>
    </ng-container>
    <ng-container *ngIf="item.type == 'link'">
      <div>
        <a class="cs-link-white" href="#">{{ item.menuTitle }}</a>
      </div>
    </ng-container>
  </div>
</div>
<div
  *ngIf="activeMenu"
  style="height: 200px; width: 100%; background-color: #c8c8c8;"
  class="dropdown-menu"
  [class.show]="isDropdownOpen[activeMenu.menuCode]"
>
  <div>
    Hello from {{ activeMenu.menuCode }}
    <button (click)="triggerAction()">Button</button>
  </div>
</div>

CSS:

.flex-container {
  background-color: #2f333a;
  display: flex;
  align-items: center;
}

.cs-link-white {
  display: flex;
  color: white;
  text-decoration: none;
  font-family: inherit;
  -webkit-box-align: center;
  align-items: center;
  padding: 0 15px;
  min-height: 44px;
  letter-spacing: 0.2px;
  font-size: 14px;
  font-weight: 500;
  font-style: normal;
  line-height: normal;
}

.show {
  display: block;
}

TypeScript Code:

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

interface NavigationItem {
  menuTitle: string;
  menuCode: string;
  type: 'dropdown' | 'link';
}

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css'],
  standalone: true,
  imports: [CommonModule],
})
export class NavigationComponent {
  activeMenu!: NavigationItem;

  isDropdownOpen: any = {
    dropdown1: false,
    dropdown2: false,
    dropdown3: false,
  };

  navigations: NavigationItem[] = [
    {
      menuTitle: 'Dropdown 1',
      menuCode: 'dropdown1',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 2',
      menuCode: 'dropdown2',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 3',
      menuCode: 'dropdown3',
      type: 'dropdown',
    },
    {
      menuTitle: 'Link1',
      menuCode: 'link1',
      type: 'link',
    },
    {
      menuTitle: 'Link2',
      menuCode: 'link2',
      type: 'link',
    },
  };

  constructor() {}

  showDropdown(item: NavigationItem) {
    this.activeMenu = item;
    this.isDropdownOpen[item.menuCode] = true;
  }

  hideDropdown(item: NavigationItem) {
    this.activeMenu = item;
    this.isDropdownOpen[item.menuCode] = false;
  }

  triggerAction() {
    console.log('button clicked');
  }
}

https://i.sstatic.net/gOtA2.png

Answer №1

To enable the hover functionality on the dropdown menu, a setTimeout function can be added to toggle the flag when a mouseover event occurs.

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';

interface NavigationItem {
  menuTitle: string;
  menuCode: string;
  type: 'dropdown' | 'link';
}

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css'],
  standalone: true,
  imports: [CommonModule],
})
export class NavigationComponent {
  activeMenu: NavigationItem = {
    menuTitle: 'Dropdown 1',
    menuCode: 'dropdown1',
    type: 'dropdown',
  };

  isDropdownOpen: any = {
    our_products: false,
    home_kitchen: false,
    toys: false,
    dropdown2: false,
    dropdown3: false,
  };

  navigations: NavigationItem[] = [
    {
      menuTitle: 'Dropdown 1',
      menuCode: 'dropdown1',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 2',
      menuCode: 'dropdown2',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 3',
      menuCode: 'dropdown3',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 4',
      menuCode: 'dropdown4',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 5',
      menuCode: 'dropdown5',
      type: 'dropdown',
    },
    {
      menuTitle: 'Dropdown 6',
      menuCode: 'dropdown6',
      type: 'dropdown',
    },
    {
      menuTitle: 'Link1',
      menuCode: 'link1',
      type: 'link',
    },
    {
      menuTitle: 'Link2',
      menuCode: 'link2',
      type: 'link',
    },
  ];

  isDropdownOpenv1 = false;

  constructor() {}

  showDropdown(item: NavigationItem) {
    this.activeMenu = item;
    this.isDropdownOpen[item.menuCode] = true;
  }

  hideDropdown(event: any, item: NavigationItem) {
    console.log(event);
    const relatedTarget = event?.relatedTarget;
    if (relatedTarget?.classList.contains('dropdown-menu')) {
      return;
    }
    this.activeMenu = item;
    setTimeout(() => {
      this.isDropdownOpen[item.menuCode] = false;
    });
  }

  isMobileView(): boolean {
    return window.innerWidth < 992;
  }

  showDropdownv1() {
    this.isDropdownOpenv1 = true;
  }

  hideDropdownv1() {
    this.isDropdownOpenv1 = false;
  }

  triggerAction() {
    this.isDropdownOpen[this.activeMenu.menuCode] = false;
    console.log('button clicked');
  }
}

stackblitz

Answer №2

To enhance your dropdown functionality, simply incorporate mouse enter and mouse leave events into the code for your dropdown menu element. This will allow you to easily show and hide the dropdown as needed.

Example Code

<div
  *ngIf="showDropdown"
  (mouseenter)="handleMouseEnter()"
  (mouseleave)="handleMouseLeave()"
  style="height: 200px; width: 100%; background-color: #c8c8c8;"
  class="dropdown-menu"
  [class.show]="isDropdownVisible"
>
  <div>
    Hello from Dropdown Menu
    <button (click)="performAction()">Button</button>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize Typescript to inject types into a library

I have a code snippet that reads data from a JSON file and creates a type based on it, which is then used for further operations. import jsonData from './mydata.json' type CustomType = typeof jsonData .... This process ensures that the generate ...

Angular calendar module for easy scheduling

I am currently utilizing the angular full calendar day grid plugin. The format of my json data is as follows: [ {“id”:2,“start_time”:“2019-08-15 16:52:00”}, {“id”:3, “start_time”:“2019-09-23 18:55:00”} ] Unfortunately, angular f ...

Encountered an issue resolving peer dependency during package installation

I recently developed an Angular 9 library that consists of several packages. However, when running npm install, I encountered an error with one of the external packages stating 'Could not resolve peer dependency @angular/common@"^8.2.6"". I ...

"Angular SwtAlert2: The Ultimate Multi-Selection Tool

I am trying to integrate the ng-select directive into SweetAlert2, but the code snippet below is not working as expected: const { value: formValues } = await swal.fire({ title: 'Multiple inputs', html: '<ng-select id=" ...

Discovering the Java Map's value in Typescript

My application's backend is built using Spring Boot and the frontend is Angular 7. I need to send a map as a response, like this: Map<String, Object> additionalResponse = new HashMap<>() { { put("key1"," ...

Is it possible to both break down a function parameter and maintain a named reference to it at the same time?

When working with stateless functional components in React, it is common to destructure the props object right away. Like this: export function MyCompoment({ title, foo, bar }) { return <div> title: {title}, ...</div> } Now ...

Angular 2 - Constructing dates in constructor - Error: Type 'Date' cannot be assigned to type 'string'

In my attempt to generate a fresh date object for an ngx-chart by referencing this specific example, I came across the following code snippet: constructor() { this.data = this.multi.map(group => { group.series = group.series.map(dataItem =& ...

Dealing with mouseover and mouseout events for ul li elements in Angular 9: An easy guide

Having trouble showing and hiding the span tag using mouseover and mouseout events. The ul and li elements are generating dynamically, so I attempted to toggle the display between block and none but it is not working as expected. Does anyone have a solutio ...

Sign up for notifications using NGRX

How can I incorporate CompanyEffects in my AppModule after receiving a response from the AppConfigService on the server? Effect registration within AppModule EffectsModule.forRoot([CompanyEffects]), CompanyEffects Implementation export class CompanyEff ...

Closing notifications in Bootstrap 5.1 with the help of Ajax

I am utilizing bootstrap 5.1 alerts to display custom messages after an Ajax call. I also want the ability to dismiss the alert as necessary, which can be done with a dismiss button provided by bootstrap. Below is the PHP code I am using : <div class=& ...

What is the best way to remove all validators from a different component in Angular 7 using reactive forms?

I need to find a way to clear all validation in a form group on a sibling component when a boolean value is selected on another component within the same application. Is there a solution for achieving this? We have implemented a method in our application ...

Unable to reference the namespace 'ThemeDefinition' as a valid type within Vuetify

Looking to develop a unique theme for Vuetify v3.0.0-alpha.10 and I'm working with my vuetify.ts plugin file. import "@mdi/font/css/materialdesignicons.css"; import "vuetify/lib/styles/main.sass"; import { createVuetify, ThemeDefinition } from "v ...

Angular 2 - Issue with ngOnInit not being called upon routing to the same component multiple times

Currently, I am developing a web application using Angular 2. When there is data in my array, I navigate to the xyz component and store it in a service component. The ngOnInit() method of the xyz component retrieves data from the service and displays it ...

Variables within Angular2 services are resetting when the route changes

I have been utilizing a service to monitor the status of my model. I have several components that need to access the variables and properties of this service. The issue arises when the first component initializes, sets the model, but upon trying to access ...

searchByTextContentUnderListItemAnchorTag

I would like to utilize the getByRole function for writing my test. However, I am encountering issues when using linkitem or 'link' as the role. It seems that I cannot find the desired element. // encountered error TestingLibraryElementError: The ...

Tips for implementing an automatic refresh functionality in Angular

I am dealing with 3 files: model.ts, modal.html, and modal.ts. I want the auto refresh feature to only happen when the modal is open and stop when it is closed. The modal displays continuous information. modal.htlm : <button class="btn btn-success ...

Is Angular capable of determining which module to load for the frontend, or does it always need to load the entire application with all modules?

Is it possible for Angular 2 to selectively load specific modules for the frontend, or does it always have to load the entire application with all modules included? ...

What is the best way to ensure that the operations are not completed until they finish their work using RX

Is there a way to make RXJS wait until it finishes its work? Here is the function I am using: getLastOrderBeta() { return this.db.list(`Ring/${localStorage.getItem('localstorage')}`, { query: { equalTo: fa ...

Dynamic Data Binding in Ionic 2

One challenge I am facing is with creating my own info window for a Google Maps marker. Whenever I click on the marker, a div is displayed but the information inside the div does not get updated. It seems like the event.title remains unchanged from its old ...

The ngFor directive in Angular should be used with the Filter pipe to ensure that

Having a Filter implemented in my Angular Project that fetches data from Firebase. The current status in the Filter is as follows: Name 1: Lea Muster Name 2: Bruno Mustermann Name 3: Lea Muster Name 4: Gabriela Musterfrau The goal is to show duplicate e ...