J'ai suivi ce qui suit pour installer bootstrap 4 dans mon projet Angular 2 project: Réponse acceptée, après les premiers 1,2,3 et 4) étapes
Cependant, lorsque j'ajoute le HTML
suivant à mon composant d'en-tête:
<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">[email protected]</a>
<div class="dropdown-menu" aria-labelledby="nav-dropdown">
<a href="#" class="dropdown-item">Sign Out</a>
</div>
</li>
</ul>
</div>
Comme vous pouvez le voir, c'est une liste déroulante en gros, lorsque je clique sur la liste déroulante, la page est actualisée, à la place, elle n'affiche pas l'option de "déconnexion".
C'est mon angular-cli.json
section styles:
"styles": [
"styles.css",
"../node_modules/bootstrap/dist/css/bootstrap.min.css"
],
Et à l'intérieur de mon module Angular 2:
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
J'importe ensuite NgbModule dans la section des importations.
J'ai clairement manqué quelque chose, quelqu'un peut-il faire la lumière sur ce que c'est peut-être exactement?
Veuillez installer ng-bootstrap à partir de ce lien Mise en route avec la commande suivante:
npm `install --save @ng-bootstrap/ng-bootstrap`
Importez-le sur app.module.ts
comme
import `{NgbModule} from '@ng-bootstrap/ng-bootstrap';`
Importer sur
imports:[
NgbModule.forRoot(),
]
Ajouter ngbDropdown
dans la liste déroulante
Ajouter ngbDropdownToggle
dans la liste déroulante Basculer DOM
Ajouter ngbDropdownMenu
dans le menu déroulant 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>
Variation sur @VictorLuchian pour les plus récents BS4 beta, il semble que la classe 'show' doit également être ajoutée dans le menu déroulant. Cette version comprend un clic à l'extérieur de la fermeture au lieu de la souris
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')
}
}
}
Certains plugins et composants CSS dépendent d'autres plugins. Si vous incluez des plugins individuellement, assurez-vous de vérifier ces dépendances dans les documents. Notez également que tous les plugins dépendent de jQuery (cela signifie jQuery doit être inclus avant les fichiers de plugin ).
Dans .angular-cli.json
ajoutez les lignes suivantes à la section des scripts:
# version 4.x
"scripts": [
"../node_modules/jquery/dist/jquery.js",
"../node_modules/bootstrap/dist/js/bootstrap.js",
]
Comme l'a dit Andrien, vous pouvez simplifier le code comme ceci.
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')
}
Exemple de code StackBliz Link
Tout d'abord Bootstrap 3 & 4 Les classes d'état actives déroulantes sont différentes
Dans Boostrap 3: Dans l'état déroulant ouvert; L'élément parent .dropdown-toggle est ajouté ' open' Classe CSS
Où, comme dans Boostrap 4, utilisez la classe CSS " show" Dans le menu déroulant ouvert. Ici, l'élément parent de l'élément .dropdown-toggle et l'élément frère suivant avec la classe CSS .dropdown-menu sont ajoutés " show" css Class
Par conséquent, pour que la liste déroulante boostrap 4 fonctionne avec angular 4, nous allons créer une nouvelle classe de directive angular et l'ajouter à la liste déroulante boostrap dans le modèle angular
Étape 1 - Créez une nouvelle directive angular dans 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;
}
}
}
Étape 2: Importez cette directive dans app.module.ts
import { NgBoostrapDropdownDirective } from './directives/ng-boostrap-dropdown.directive';
@NgModule({
declarations: [ AppComponent, NgBoostrapDropdownDirective ],
})
Étape 3: Appliquer la directive dans le modèle en utilisant 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>
Inspiré par la première version de Rahul Talar (Étape 1 - Nouvelle caisse angular dans ng-boostrap-dropdown.directive.ts), j'ai fait quelques similaires en utilisant 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);
}
}
Avec Angular 8 et Bootstrap 4.2 c'est la solution de travail que j'utilise:
1- J'ai d'abord créé une directive personnalisée. Ce qu'il fait, c'est écouter l'événement au clic du conteneur déroulant et basculer la classe .show de l'élément .dropdown-menu (comportement standard de Bootstrap 4). De plus, cela fermera le menu déroulant s'il y a un clic partout ailleurs sur le document.
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- Une fois votre directive créée et enregistrée. Assurez-vous d'appliquer la directive à l'élément déroulant, comme dans cet exemple:
<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>
navbar.component.html
<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>
dropdown.directive.ts
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');
}
}
j'ai utilisé une approche différente pour obtenir une liste déroulante sur la barre de navigation collpased.
ÉTAPE 1 Ajouter un événement de clic sur le bouton bascule de la barre de navigation
<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: implémenter la fonction à l'intérieur du composant Navbar.ts (le modèle html ci-dessus est utilisé dans le composant navbar)
import { Component} from '@angular/core';
export class HeaderComponent {
buttontoggled:boolean:false;
OnClik(){
this.buttontoggled=!this.buttontoggled;
}
Étape basé sur le bouton bascule de la barre de navigation, cliquez sur ajouter une classe show (bootstrap 4) ou open
pour la précédente bootstrap versions. nous pouvons utiliser la directive ngClass pour cela
<div class="collapse navbar-collapse " [ngClass]="{'show': buttontoggled}" id="myNavbar">
Flux de travail
Le bouton bascule de la barre de navigation sera visible lorsque la barre de navigation se réduira pour des résolutions plus petites
en gérant l'événement de clic de bouton, nous pouvons définir un indicateur pour vérifier si le bouton a cliqué ou non
Sur la base de ce drapeau, nous lierons la classe css show à navabr div en utilisant la directive ngClass
Quelqu'un a créé une nouvelle version de la bibliothèque de modèles spécialement conçue pour Angular 2+. Selon le site Web, elle a été développée par ng-team, bien que le lien qu'il donne obtienne une réponse 404. Il fonctionne, cependant, et je l'ai utilisé à plusieurs endroits tout au long de mon projet actuel. Il vous suffira de récupérer la bibliothèque avec npm. Toutes les instructions sont sur ce site:
http://valor-software.com/ngx-bootstrap/#/
Cette page vous montre toutes les instructions d'installation et d'utilisation dont vous avez besoin pour commencer. J'espère que ça aide!
import { Directive, HostListener, HostBinding, ElementRef } from '@angular/core';
@Directive({
selector: '[appDropdown]'
})
export class DropdownDirective {
constructor(private _el: ElementRef) {
}
@HostBinding('class.show') isOpen = false;
@HostListener('click') toggleOpen(){
this.isOpen=!this.isOpen;
if(this.isOpen){
this._el.nativeElement.querySelector('.dropdown-menu').classList.add('show');
}
else{
this._el.nativeElement.querySelector('.dropdown-menu').classList.remove('show');
}
}
}
J'utilise un thème qui n'est pas construit pour Angular et il contient un bootstrap classique, j'ai eu le même problème et corrigé en modifiant le fichier bootstrap.js.
Le problème est que bootstrap écoutez les événements avec $ (document) .on et le problème est dans la partie "document".
Dans mon fichier bootstrap c'est la ligne 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();
});
Remplacez $ (document) par $ ("body") et cela fonctionnera.
$("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();
});
Le CSS doit être dans le <head></head>
tag.
Je cite du bootstrap
Copiez-collez la feuille de style
<link>
Dans votre<head>
avant toutes les autres feuilles de style pour charger notre CSS.
Je continue de citer
Ajoutez nos plugins JavaScript, jQuery et Tether vers la fin de vos pages, juste avant la balise de fermeture. Assurez-vous de placer jQuery et Tether en premier, car notre code dépend d'eux.
Assurez-vous que vous disposez de cette manière voici le lien vers la documentation bootstrap où j'obtiens ces citations https://v4-alpha.getbootstrap.com/getting-started/introduction /
et vérifiez cette réponse dans le message que vous partagez le lien https://stackoverflow.com/a/39809447/3284537