Twitter bootstrap 角度2下拉列表中的引导4不工作

Twitter bootstrap 角度2下拉列表中的引导4不工作,twitter-bootstrap,angular,Twitter Bootstrap,Angular,我遵循以下步骤将引导4安装到Angular 2项目中: 但是,当我将以下HTML添加到我的标题组件时: <nav class="navbar-dark bg-inverse"> <div class="container"> <a href="#" class="navbar-brand"></a> <ul class="nav navbar-nav float-xs-right"> <li cla

我遵循以下步骤将引导4安装到Angular 2项目中:

但是,当我将以下
HTML
添加到我的标题组件时:

<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>
在我的Angular 2模块中:

import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
然后我将NgbModule导入导入部分


我显然错过了一些东西,有人能解释一下它到底是什么吗?

CSS需要在
标签中。
我引用bootstrap的话

将样式表
复制粘贴到您的
中,然后再执行所有其他操作 样式表来加载我们的CSS

我继续引用

将我们的JavaScript插件、jQuery和Tether添加到您的 页面,就在结束标记之前。确保放置jQuery 首先是系绳,因为我们的代码依赖于它们

确保你有这样的能力 这里是引导程序文档的链接,我在这里得到了这些引用

并在分享链接的帖子中检查这个答案

有人专门为Angular 2+设计了新版本的模板库。据该网站称,它是由ng团队开发的,尽管它给出的链接得到了404响应。但它确实有效,在我当前的项目中,我已经在多个地方使用过它。你只需要用npm把图书馆拉进去。本网站提供了所有说明:


该页面显示了开始使用所需的所有安装和使用说明。我希望这有帮助

您需要添加一个下拉指令才能使其工作。 该指令如下所示:

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;
}
然后,您将添加如下属性:

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

  • 最新的BS4 beta版本的@VictorLuchian变体,似乎还需要在下拉菜单中添加“show”类。 此版本包括单击外部关闭而不是鼠标退出

    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')
        }
    }
    }
    
  • 请使用以下命令从此链接安装ng引导程序:

    npm `install --save @ng-bootstrap/ng-bootstrap`
    
  • 在app.module.ts上导入它

    import `{NgbModule} from '@ng-bootstrap/ng-bootstrap';` 
    
  • 导入

    imports:[
       NgbModule.forRoot(),
    ]
    
  • 在下拉列表中添加
    ngbDropdown

  • 在下拉切换DOM上添加
    ngbdropdownttoggle

  • 在下拉菜单DOM上添加
    ngbDropdownMenu

                <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>
    


  • 一些插件和CSS组件依赖于其他插件。如果您单独包含插件, 确保在文档中检查这些依赖项。还要注意,所有插件都依赖于 jQuery(这意味着必须在插件文件之前包含jQuery)

    .angular cli.json
    中,将以下行添加到脚本部分:

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

    我使用了一种不同的方法来获取collpased导航栏上的下拉列表

    步骤1 在导航栏切换按钮上添加单击事件

    <button type="button" class="navbar-toggle" data-toggle="collapse" (click)="OnClik()" data-target="#myNavbar"
    
    步骤3 根据导航栏切换按钮,单击添加类显示(引导4)或
    open
    ,查看以前的引导版本。 我们可以使用ngClass指令来实现这一点

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

    当Navbar geting为较小分辨率而折叠时,Navbar切换按钮将可见

    通过处理按钮点击事件,我们可以设置一个标志来检查按钮是否点击

    基于这面旗帜,我们将
    我们将使用ngClass指令将css类show绑定到navabr div

    我使用的主题不是为Angular构建的,它包含经典引导,我有同样的问题,并通过修改bootstrap.js文件进行了修复

    问题是引导程序使用$(document.on)侦听事件,问题在“document”部分

    在我的引导文件中,它是第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();
      });
    
    将$(document)更改为$(“body”),它将起作用

     $("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();
          });
    

    首先,引导3和4下拉式活动状态类不同

  • 在Boostrap 3中:处于下拉打开状态。添加了下拉切换父元素“open”CSS类

  • 其中,与boostrap4一样,使用“show”CSS类 处于下拉打开状态。这里。下拉菜单切换元素的父元素和CSS类的下一个同级元素。下拉菜单添加了“show”CSS类

  • 因此,为了使boostrap 4下拉菜单与angular 4一起工作,我们将创建新的angular指令类,并将其添加到angular模板中的boostrap下拉菜单中

    步骤1-在ng boostrap下拉列表中装入新角度指令。指令.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;
        }
      }
    
    }
    
    import { NgBoostrapDropdownDirective } from './directives/ng-boostrap-dropdown.directive';
    
    @NgModule({
    
      declarations: [ AppComponent, NgBoostrapDropdownDirective ],
    
    })
    
    import { Directive, HostBinding, HostListener, ElementRef } from '@angular/core';
    
        @Directive({
          selector: '[appDropdown]'
        })
        export class DropdownDirective {
          constructor(private elementRef: ElementRef) { }
    
          private dropdownParentEl = this.elementRef.nativeElement.closest('.dropdown');
    
          @HostListener('mouseenter') toggleOpen(){
            this.dropdownParentEl.querySelector(".dropdown-menu").classList.add('show');
          }
          @HostListener('mouseleave') toggleClose(){
            this.dropdownParentEl.querySelector(".dropdown-menu").classList.remove('show');
          }
    
          @HostListener('click') toogleOpen() {
              this.dropdownParentEl.querySelector(".dropdown-menu").classList.toggle('show');
          }
        }
    
    步骤2:在app.module.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;
        }
      }
    
    }
    
    import { NgBoostrapDropdownDirective } from './directives/ng-boostrap-dropdown.directive';
    
    @NgModule({
    
      declarations: [ AppComponent, NgBoostrapDropdownDirective ],
    
    })
    
    import { Directive, HostBinding, HostListener, ElementRef } from '@angular/core';
    
        @Directive({
          selector: '[appDropdown]'
        })
        export class DropdownDirective {
          constructor(private elementRef: ElementRef) { }
    
          private dropdownParentEl = this.elementRef.nativeElement.closest('.dropdown');
    
          @HostListener('mouseenter') toggleOpen(){
            this.dropdownParentEl.querySelector(".dropdown-menu").classList.add('show');
          }
          @HostListener('mouseleave') toggleClose(){
            this.dropdownParentEl.querySelector(".dropdown-menu").classList.remove('show');
          }
    
          @HostListener('click') toogleOpen() {
              this.dropdownParentEl.querySelector(".dropdown-menu").classList.toggle('show');
          }
        }
    
    步骤3:使用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>
    
    导航:
    
  • 按钮下拉列表: 下拉按钮

    正如Andrien所说,您可以像这样简化代码

    constructor(private _el: ElementRef) { }
    
    @HostBinding('class.show') isOpen = false;
    
    @HostListener('click') toogleOpen() {
        this.isOpen = !this.isOpen;
        this._el.nativeElement.querySelector('.dropdown-menu').classList.toggle('show')
    }
    

    navbar.component.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>
    
    <li class="nav-item dropdown show" appDropdown>
            <a class="nav-link dropdown-toggle" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              Categories
            </a>
            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
              <a routerLink="yourLInk1" class="dropdown-item">Item 1</a>
              <a routerLink="yourLInk2" class="dropdown-item">Item 2</a>
              <a routerLink="yourLInk3" class="dropdown-item">Item 3</a>
              <a routerLink="yourLInk4" class="dropdown-item">Item 4</a>
              <div class="dropdown-divider"></div>
              <a routerLink="yourLInk5" class="dropdown-item">Item 5</a>
            </div>
          </li>
    

    受Rahul Talar的第一个版本(Step 1-ng boostrap dropdown.directive.ts中的板条箱新角度指令)的启发,我使用Rendere2制作了一些类似的东西

    import { Directive, HostListener, ElementRef, Renderer2, OnInit } from '@angular/core';
    
    @Directive({
      selector: '[appDropdown]'
    })
    export class AppDropdownDirective implements OnInit {
      private isShow = false;
      private classShow = 'show';
      private parentNode: HTMLElement;
      private siblingNode: HTMLElement;
    
      constructor(private elementRef: ElementRef, private renderer: Renderer2) {}
    
      ngOnInit() {
        this.parentNode = this.renderer.parentNode(this.elementRef.nativeElement);
        this.siblingNode = this.renderer.nextSibling(this.elementRef.nativeElement);
      }
    
      @HostListener('click') open() {
        this.isShow = !this.isShow;
        if (this.isShow) {
          this.addClass();
        } else {
          this.removeClass();
        }
      }
    
      @HostListener('document:click', ['$event']) clickout(event) {
        if (this.elementRef.nativeElement !== event.target && this.isShow) {
          this.removeClass();
          this.isShow = false;
        }
      }
    
      private addClass() {
        this.renderer.addClass(this.parentNode, this.classShow);
        this.renderer.addClass(this.siblingNode, this.classShow);
      }
    
      private removeClass() {
        this.renderer.removeClass(this.parentNode, this.classShow);
        this.renderer.removeClass(this.siblingNode, this.classShow);
      }
    }
    

    对于Angular 8和Bootstrap 4.2,这是我正在使用的工作解决方案:

    1-首先,我创建了一个自定义指令。它所做的是监听下拉容器的点击事件,并切换.dropdown菜单元素的.show类(bootstrap4标准行为)。此外,如果在文档的其他地方单击,它将关闭下拉菜单

    import {Directive, ElementRef, HostBinding, HostListener, OnInit} from '@angular/core';
    
    @Directive({
      selector: '[appDropdown]'
    })
    export class DropdownDirective implements OnInit {
      dropDownMenu: HTMLElement;
      @HostListener('document:click', ['$event']) toggleOpen(event: Event) {
        if ( this.dropDownButton.nativeElement.contains(event.target) ) {
          this.dropDownMenu.classList.toggle('show');
        } else {
          this.dropDownMenu.classList.remove('show');
        }
      }
    
      constructor(private dropDownButton: ElementRef) { }
    
      ngOnInit(): void {
        this.dropDownMenu = this.dropDownButton.nativeElement.querySelector('.dropdown-menu');
      }
    }
    
    2-创建并注册指令后。确保将该指令应用于下拉元素,如本例所示:

    <div class="btn-group" appDropdown>
        <button type="button" class="btn btn-primary dropdown-toggle">Dropdown menu<span class="caret"></span></button>
        <ul class="dropdown-menu">
            <li class="dropdown-item"><a href="#">Item One</a></li>
            <li class="dropdown-item"><a href="#">Item Two</a></li>
            <li class="dropdown-item"><a href="#">Item Three</a></li>
        </ul>
    </div>
    
    
    下拉菜单