1

I am trying to implement drop down menu items on click using javascript without using jquery in angular

I tried creating seperate javascript file and specified the file path in script in angular json file. It is not working. What are the other ways to do this?

<div class="tab-dropdown">
                  <div id="dropdown" (click)="dropClick()">Open Dropdown</div>
               </div>
               <ul class="nav" role="tablist" id="navdrop">
                  <li class="nav-item">
                     <a class="nav-link active" href="#all" role="tab" data-toggle="tab" onclick="addprevtext()">All</a>
                  </li> -->
                  <li class="nav-item ">
                     <a class="nav-link " href="#social" role="tab" data-toggle="tab" onclick="addprevtext()">HR</a>
                  </li>
                  <li class="nav-item">
                     <a class="nav-link" href="#digital" role="tab" data-toggle="tab"
                        onclick="addprevtext()">Marketing
                     </a>
                  </li>
                  <li class="nav-item">
                     <a class="nav-link" href="#crm" role="tab" data-toggle="tab" onclick="changetext()">Customer Service</a>
                  </li>
                  <li class="nav-item">
                     <a class="nav-link" href="#ticketing" role="tab" data-toggle="tab"
                        onclick="changetext()">Operations</a>
                  </li>
                  <li class="nav-item">
                     <a class="nav-link" href="#coreSystem" role="tab" data-toggle="tab" onclick="changetext()">Insurance</a>
                  </li>
                  <li class="nav-item">
                     <a class="nav-link" href="#dms" role="tab" data-toggle="tab" onclick="changetext()">Financial Services</a>
                  </li>
                  <li class="nav-item">
                        <a class="nav-link" href="#manu" role="tab" data-toggle="tab" onclick="changetext()">Manufacturing
                           </a>
                     </li>
                     <li class="nav-item">
                           <a class="nav-link" href="#health" role="tab" data-toggle="tab" onclick="changetext()">Healthcare & Pharma

                              </a>
                        </li>
                        <li class="nav-item">
                              <a class="nav-link" href="#it" role="tab" data-toggle="tab" onclick="changetext()">IT

                                 </a>
                           </li>

               </ul>

js File

function showDropdown() {
document.getElementById("dropdown").onclick = function() {myFunction()};

function myFunction() {
  document.getElementById("navdrop").classList.toggle("show");
}
}

ts file

dropClick() {
    showDropdown();

  }

Drop down menu should open on clicking

Here's an MCVE: https://stackblitz.com/edit/angular-wrmrvu

random_user_name
  • 25,694
  • 7
  • 76
  • 115
divya dave
  • 471
  • 1
  • 9
  • 28

3 Answers3

0

I would go with @ViewChild() and ElementRef, no need to write extra code in the seperate .js file or no need to create any directive.

TS Code:

Import this:

import {  ElementRef, ViewChild } from '@angular/core';

and:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = 'Angular';

  @ViewChild('navdrop', null) navdrop: ElementRef; // Angular Version 8
  @ViewChild('navdrop') navdrop: ElementRef; // Angular Version < 8

  dropClick() {
    this.navdrop.nativeElement.classList.toggle("visibility");
  }
}

CSS:

.visibility {
  display: none;
}

HTML Code:

                           This is important
                               \/\/\/\/
<ul class="nav" role="tablist" #navdrop id="navdrop">
   ... 
    your other HTML markup
   ...
</ul>

Working_Demo

Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
  • 1
    just wondering, how can you create a class called show with display none in it – Mcanic Nov 26 '19 at 14:05
  • @Mcanic Well, its all about naming convensions, Suggest anything if you can name it well! – Prashant Pimpale Nov 27 '19 at 05:29
  • Clicking on the menu and showing the menu items, how can you make the menu hover over existing content, and not taking up space and pushing the existing content down? – J K Sep 28 '20 at 05:19
0

You also need to be able to open several dropdowns at the same time and you need it to close if you press outside of it. You will need at service to control that.

Main directive

@Directive({
    selector: '[dropDown]'
})
export class Dropdown implements AfterContentInit, OnDestroy {
    private toggleSubscription: Subscription = new Subscription();
    private outSideSubscription: Subscription = new Subscription();
    @ContentChild(DropdownToogle) ddToggle: DropdownToogle;
    @HostBinding('class.dropdown') dropDownClass = true;
    @HostBinding('class.opened') opened: boolean;

    constructor(private element: ElementRef, private dropDownService: DropdownService) {
    }

    ngAfterContentInit(): void {
        this.toggleSubscription = this.ddToggle.clicked.subscribe(() => {
            this.opened = !this.opened;
            if (this.opened) {
                this.outSideSubscription = this.dropDownService.getAppClick().subscribe((target: any) => {
                    const clickedInside = this.element.nativeElement.contains(target);
                    if (!clickedInside) {
                        this.outSideSubscription.unsubscribe();
                        this.opened = false;
                    }
                });
            } else {
                this.outSideSubscription.unsubscribe();
            }
        });
    }

    ngOnDestroy(): void {
        this.toggleSubscription.unsubscribe();
        this.outSideSubscription.unsubscribe();
    }
}

And the dropdown toggle

@Directive({
    selector: '[dropDownToggle]'
})
export class DropdownToogle {
    @Output() clicked = new EventEmitter();
    @HostBinding('class.dropdown-toggle') true = true;
    @HostListener('click', ['$event']) onclick() {
        this.clicked.emit();
    }

}

And the service

@Injectable()
export class DropdownService {
    private subject = new Subject<any>();
    constructor() {
        fromEvent(document, 'click').subscribe((event: any) => {
            this.subject.next(event.target);
        });
    }
    getAppClick(): Observable<any> {
        return this.subject.asObservable();
    }
}

Basic css

.dropdown{
  position: relative;
  float: right;
}
.dropdown .opened .dropdown-menu {
      display: block;
  }

.dropdown .dropdown-menu {
    display: none;
    right: 0;
    position: absolute;
    min-width: 160px;
}

You will need to add styling for the buttons or the anchorlinks within the dropdown And finally the usage

<div dropDown>
  <button dropDownToggle>A dropdown</button>
  <div class="dropdown-menu">
    <button>Do something</button>
    <button>Something else</button>
  </div>
</div>
Jens Alenius
  • 1,931
  • 2
  • 16
  • 20
0

This is a solution for bootstrap 4 with angular.

In your package.json you need

dependencies: {
  "@ng-bootstrap/ng-bootstrap": "^4.0.2",
  "bootstrap": "^4.3.1",
  ...
}

In your app.module.ts file you will need to add a module

imports: [
  ...
  NgbModule.forRoot()
]

All of the above is to enable the following 3 directives: ngbDropdown, ngbDropdownToggle and ngbDropdownMenu.

So, now you can use those in the template files of your components. e.g. for a dropdown with caption "More ..." and one menu item "Item", you would need something like this:

  <div ngbDropdown>
    <a ngbDropdownToggle
      class="btn btn-primary dropdown-toggle"
      id="navbarDropdownMenuLink"
      data-toggle="dropdown"
      aria-haspopup="true" aria-expanded="false">
      More...
    </a>
    <div ngbDropdownMenu
      class="dropdown-menu"
      aria-labelledby="navbarDropdownMenuLink">
      Item
    </div>
  </div>

You can find more examples in the official documentation of ng bootstrap.

bvdb
  • 22,839
  • 10
  • 110
  • 123