bootstrap 4 in Angular 2 dropdown not working

匿名 (未验证) 提交于 2019-12-03 03:02:02

问题:

I have followed the following to install bootstrap 4 into my Angular 2 project: Accepted Answer, following the first 1,2,3 and 4 steps

However when I add the following HTML to my header component:

<nav class="navbar-dark bg-inverse"> <div class="container">     <a href="#" class="navbar-brand"></a>     <ul class="nav navbar-nav float-xs-right">         <li class="nav-item dropdown">             <a href="#" class="nav-link dropdown-toggle" id="nav-dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">SomeEmail@hotmail.com</a>             <div class="dropdown-menu" aria-labelledby="nav-dropdown">                 <a href="#" class="dropdown-item">Sign Out</a>             </div>         </li>     </ul> </div> 

As you can see its a dropdown basically, when I click on the dropdown the page refreshes, instead it doesn't display the 'sign out' option.

This is my angular-cli.json styles section:

"styles": [   "styles.css",   "../node_modules/bootstrap/dist/css/bootstrap.min.css" ],     

And inside my Angular 2 module:

import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; 

I then import NgbModule into the imports section.

I've clearly missed something, can someone shed any light into what it maybe exactly?

回答1:

Variation on @VictorLuchian for newest BS4 beta, it seems 'show' class need to be added on the dropdown-menu as well. This version include a click outside close instead of mouseout

import { Directive,HostListener,HostBinding, ElementRef } from '@angular/core';  @Directive({   selector: '[customdropdown]' }) export class CustomDropdownDirective {  private isOpen: boolean =false; constructor(private _el: ElementRef) {   }  @HostBinding('class.show') get opened() {     return this.isOpen; } @HostListener('click') open() {     this.isOpen = true;     this._el.nativeElement.querySelector('.dropdown-menu').classList.add('show')                 } @HostListener('document:click', ['$event.target']) close (targetElement) {     let inside: boolean = this._el.nativeElement.contains(targetElement);     if(!inside) {         this.isOpen = false;         this._el.nativeElement.querySelector('.dropdown-menu').classList.remove('show')     } } } 


回答2:

Some plugins and CSS components depend on other plugins. If you include plugins individually, make sure to check for these dependencies in the docs. Also note that all plugins depend on jQuery (this means jQuery must be included before the plugin files).

In .angular-cli.json add the following lines to the scripts section:

# version 4.x   "scripts": [     "../node_modules/jquery/dist/jquery.js",     "../node_modules/bootstrap/dist/js/bootstrap.js",   ] 

Checkout definition here



回答3:

You will need to add a dropdown directive in order for this to work. The directive looks like this:

import { Directive,HostListener,HostBinding } from '@angular/core';  @Directive({ selector: '[appcustomdropdown]' }) export class CustomdropdownDirective {  constructor() { }  @HostBinding('class.open') get opened() { return this.isOpen; } @HostListener('click') open() { this.isOpen=true; } @HostListener('mouseleave') close() { this.isOpen=false; } private isOpen=false; } 

Then, you will add the attribute like so:

<li class="nav-item dropdown" appcustomdropdown > 


回答4:

  1. Please install ng-bootstrap from this link Getting Started with the following command:

    npm `install --save @ng-bootstrap/ng-bootstrap` 
  2. Import it on app.module.ts like

    import `{NgbModule} from '@ng-bootstrap/ng-bootstrap';`  
  3. Import on

    imports:[    NgbModule.forRoot(), ] 
  4. Add ngbDropdown on dropdown

  5. Add ngbDropdownToggle on dropdown Toggle DOM

  6. Add ngbDropdownMenu on dropdown menu DOM

                <li ngbDropdown  class="nav-item dropdown" >                 <a ngbDropdownToggle class="nav-link dropdown-toggle"  href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">                  Manage                 </a>                 <div ngbDropdownMenu  class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">                   <a class="dropdown-item" href="#">Save Data</a>                   <a class="dropdown-item" href="#">Fetch Data</a>                  </div>               </li>           </ul> 


回答5:

The CSS needs to be in the <head></head> tag.
I quote from bootstrap

Copy-paste the stylesheet <link> into your <head> before all other stylesheets to load our CSS.

I continue quoting

Add our JavaScript plugins, jQuery, and Tether near the end of your pages, right before the closing tag. Be sure to place jQuery and Tether first, as our code depends on them.

Make sure that you have in this way here is the link to bootstrap documentation where i get this quotes https://v4-alpha.getbootstrap.com/getting-started/introduction/

and check this answer in the post that you share the link https://stackoverflow.com/a/39809447/3284537



回答6:

Somebody has created a new version of the template library specifically design for Angular 2+. According to the website, it was developed by ng-team, although the link it gives gets a 404 response. It does work, though, and I have used it in multiple places throughout my current project. You'll just have to pull in the library with npm. All of the instructions are on this website:

http://valor-software.com/ngx-bootstrap/#/

That page shows you all of the install and usage instructions you need to get started. I hope this helps!



回答7:

i have used a different approach for getting drop down on collpased navbar.

STEP 1 Add click event on navbar toggle button

<button type="button" class="navbar-toggle" data-toggle="collapse" (click)="OnClik()" data-target="#myNavbar" 

Html

    <nav class="navbar navbar-inverse">   <div class="container-fluid">     <div class="navbar-header">       <button type="button" class="navbar-toggle" data-toggle="collapse" (click)="OnClik()" data-target="#myNavbar">         <span class="icon-bar"></span>         <span class="icon-bar"></span>         <span class="icon-bar"></span>       </button>       <a class="navbar-brand" href="#">WebSiteName</a>     </div>     <div class="collapse navbar-collapse " [ngClass]="{'show': buttontoggled}" id="myNavbar">       <ul class="nav navbar-nav">         <li class="active"><a href="#">Home</a></li>         <li class="dropdown">           <a class="dropdown-toggle" data-toggle="dropdown" href="#">Page 1 <span class="caret"></span></a>           <ul class="dropdown-menu">             <li><a href="#">Page 1-1</a></li>             <li><a href="#">Page 1-2</a></li>             <li><a href="#">Page 1-3</a></li>           </ul>         </li>         <li><a href="#">Page 2</a></li>         <li><a href="#">Page 3</a></li>       </ul>       <ul class="nav navbar-nav navbar-right">         <li><a href="#"><span class="glyphicon glyphicon-user"></span> Sign Up</a></li>         <li><a href="#"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>       </ul>     </div>   </div> </nav> 

Step2: implement the function inside Navbar component.ts (Above navbar html template is used inside navbar component)

import { Component} from '@angular/core';     export class HeaderComponent  {       buttontoggled:boolean:false;      OnClik(){       this.buttontoggled=!this.buttontoggled;     } 

Step 3 based on the navbar toggle button click add class show(bootstrap 4) or open for previous bootstrap versions. we can use ngClass Directive for this

 <div class="collapse navbar-collapse " [ngClass]="{'show': buttontoggled}" id="myNavbar"> 

Work flow

Navbar toggle button will be visible when navbar geting collapsed for smaller resolutions

by handling the button click event we can set one flag to check if the button clicked or not

Based on this flag we will we will bind the css class show to navabr div using ngClass directive



回答8:

I am using theme which is not build for Angular and it contain classic bootstrap, I had same issue and fixed by modifying bootstrap.js file.

Issue is that bootstrap listen events with $(document).on and problem is in "document" part.

In my bootstrap file it is line 18001

 /**    * ------------------------------------------------------------------------    * Data Api implementation    * ------------------------------------------------------------------------    */     $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {     event.preventDefault();     event.stopPropagation();      Dropdown._jQueryInterface.call($(this), 'toggle');   }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {     e.stopPropagation();   }); 

Change $(document) to $("body") and it will work.

 $("body").on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {         event.preventDefault();         event.stopPropagation();          Dropdown._jQueryInterface.call($(this), 'toggle');       }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {         e.stopPropagation();       }); 


回答9:

Example Code StackBliz Link

Firstly Bootstrap 3 & 4 Drop down active state classes are different

  1. In Boostrap 3 : In dropdown open state; .dropdown-toggle parent element is added 'open' CSS class

  2. Where as in Boostrap 4 make use of "show" CSS class In drop down open state. Here .dropdown-toggle element's parent element and next sibling element with CSS class .dropdown-menu are added "show" css Class

Hence to make boostrap 4 dropdown working with angular 4 we will create new angular directive class and add it to boostrap dropdown in angular template

Step 1 - Crate new angular directive in ng-boostrap-dropdown.directive.ts

import { Directive, HostListener, ElementRef } from '@angular/core';  @Directive({   selector: '[appNgBoostrapDropdown]' }) export class NgBoostrapDropdownDirective {    private isShow: boolean = false;   private dropdownParentEl = this.elementRef.nativeElement.closest('.dropdown');   constructor(private elementRef: ElementRef) { }     @HostListener('click') open() {     this.isShow = !this.isShow;     if (this.isShow) {       this.dropdownParentEl.classList.add('show');       this.dropdownParentEl.querySelector(".dropdown-menu").classList.add('show');     } else {       this.dropdownParentEl.classList.remove('show');       this.dropdownParentEl.querySelector(".dropdown-menu").classList.remove('show');     }   }    @HostListener('document:click', ['$event'])   clickout(event) {     if (this.elementRef.nativeElement.contains(event.target) && this.isShow) {       this.dropdownParentEl.classList.add('show');       this.dropdownParentEl.querySelector(".dropdown-menu").classList.add('show');     } else {       this.dropdownParentEl.classList.remove('show');       this.dropdownParentEl.querySelector(".dropdown-menu").classList.remove('show');       this.isShow = false;     }   }  } 

Step 2 : Import this Directive in app.module.ts

import { NgBoostrapDropdownDirective } from './directives/ng-boostrap-dropdown.directive';  @NgModule({    declarations: [ AppComponent, NgBoostrapDropdownDirective ],  }) 

Step 3 : Apply directive in Template using appNgBoostrapDropdown

NAVIGATION :        <li class="nav-item dropdown" >             <a class="nav-link dropdown-toggle" appNgBoostrapDropdown  href="#" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>             <div class="dropdown-menu" aria-labelledby="dropdown01">               <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>           </li>         </ul>  BUTTON DROPDOWN :   <div class="dropdown">   <button class="btn btn-secondary dropdown-toggle" appNgBoostrapDropdown type="button" id="dropdownMenuButton" data-toggle="dropdown" 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> 

Example Code StackBliz Link



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!