Dialogue angulaire 2.0 et Modal
J'essaie de trouver quelques exemples sur la façon de faire une boîte de dialogue modale de Confirmation dans Angular 2.0. J'ai utilisé Bootstrap dialog pour Angular 1.0 et incapable de trouver des exemples dans le web pour Angular 2.0. J'ai également vérifié les documents angular 2.0 sans succès.
Existe-t-il un moyen d'utiliser la boîte de dialogue Bootstrap avec Angular 2.0?
Merci!
9 réponses
- angulaire 2 et plus
- Bootstrap css (l'animation est préservée)
- PAS de JQuery
- PAS de bootstrap.js
- prend en charge contenu modal personnalisé (tout comme la réponse acceptée)
- récemment ajouté le support pour plusieurs modaux les uns sur les autres .
`
@Component({
selector: 'app-component',
template: `
<button type="button" (click)="modal.show()">test</button>
<app-modal #modal>
<div class="app-modal-header">
header
</div>
<div class="app-modal-body">
Whatever content you like, form fields, anything
</div>
<div class="app-modal-footer">
<button type="button" class="btn btn-default" (click)="modal.hide()">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</app-modal>
`
})
export class AppComponent {
}
@Component({
selector: 'app-modal',
template: `
<div (click)="onContainerClicked($event)" class="modal fade" tabindex="-1" [ngClass]="{'in': visibleAnimate}"
[ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<ng-content select=".app-modal-header"></ng-content>
</div>
<div class="modal-body">
<ng-content select=".app-modal-body"></ng-content>
</div>
<div class="modal-footer">
<ng-content select=".app-modal-footer"></ng-content>
</div>
</div>
</div>
</div>
`
})
export class ModalComponent {
public visible = false;
public visibleAnimate = false;
public show(): void {
this.visible = true;
setTimeout(() => this.visibleAnimate = true, 100);
}
public hide(): void {
this.visibleAnimate = false;
setTimeout(() => this.visible = false, 300);
}
public onContainerClicked(event: MouseEvent): void {
if ((<HTMLElement>event.target).classList.contains('modal')) {
this.hide();
}
}
}
Pour afficher la toile de fond , Vous aurez besoin de quelque chose comme ceci CSS:
.modal {
background: rgba(0,0,0,0.6);
}
L'exemple permet maintenant de plusieurs auxiliaires modaux en même temps . (voir la méthode onContainerClicked()
).
Pour les utilisateurs CSS Bootstrap 4 , vous devez effectuer 1 Modification mineure (car un nom de classe CSS a été mis à jour à partir de Bootstrap 3). Cette ligne:
[ngClass]="{'in': visibleAnimate}"
doit être remplacé par:
[ngClass]="{'show': visibleAnimate}"
Démontrer, voici une plunkr
Voici un exemple assez décent de la façon dont vous pouvez utiliser le modal Bootstrap dans une application Angular2 sur GitHub .
L'essentiel est que vous pouvez envelopper l'initialisation de bootstrap html et jquery dans un composant. J'ai créé un composant modal
réutilisable qui vous permet de déclencher un open en utilisant une variable de modèle.
<button type="button" class="btn btn-default" (click)="modal.open()">Open me!</button>
<modal #modal>
<modal-header [show-close]="true">
<h4 class="modal-title">I'm a modal!</h4>
</modal-header>
<modal-body>
Hello World!
</modal-body>
<modal-footer [show-default-buttons]="true"></modal-footer>
</modal>
Il vous suffit d'installer le package npm et d'enregistrer le module modal dans votre module app:
import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
@NgModule({
imports: [Ng2Bs3ModalModule]
})
export class MyAppModule {}
C'est une approche simple qui ne dépend pas de jquery ou de toute autre bibliothèque sauf Angular 2. Le composant ci-dessous (errorMessage.ts) peut être utilisé comme vue enfant de n'importe quel autre composant. C'est simplement un modal bootstrap qui est toujours ouvert ou affiché. Sa visibilité est régie par la déclaration ngIf.
ErrorMessage.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-error-message',
templateUrl: './app/common/errorMessage.html',
})
export class ErrorMessage
{
private ErrorMsg: string;
public ErrorMessageIsVisible: boolean;
showErrorMessage(msg: string)
{
this.ErrorMsg = msg;
this.ErrorMessageIsVisible = true;
}
hideErrorMsg()
{
this.ErrorMessageIsVisible = false;
}
}
ErrorMessage.html
<div *ngIf="ErrorMessageIsVisible" class="modal fade show in danger" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Error</h4>
</div>
<div class="modal-body">
<p>{{ErrorMsg}}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" (click)="hideErrorMsg()">Close</button>
</div>
</div>
</div>
</div>
Ceci est un exemple de contrôle parent (un code non pertinent a été omis pour brièveté):
Parent.ts
import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/common';
import {Router, RouteSegment, OnActivate, ROUTER_DIRECTIVES } from '@angular/router';
import { OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-application-detail',
templateUrl: './app/permissions/applicationDetail.html',
directives: [ROUTER_DIRECTIVES, ErrorMessage] // Note ErrorMessage is a directive
})
export class ApplicationDetail implements OnActivate
{
@ViewChild(ErrorMessage) errorMsg: ErrorMessage; // ErrorMessage is a ViewChild
// yada yada
onSubmit()
{
let result = this.permissionsService.SaveApplication(this.Application).subscribe(x =>
{
x.Error = true;
x.Message = "This is a dummy error message";
if (x.Error) {
this.errorMsg.showErrorMessage(x.Message);
}
else {
this.router.navigate(['/applicationsIndex']);
}
});
}
}
Parent.html
<app-error-message></app-error-message>
// your html...
J'utilise ngx-bootstrap pour mon projet.
Vous pouvez trouver la démo ici
Le github est ici
Comment utiliser:
Installez ngx-bootstrap
Importation de votre module
// RECOMMENDED (doesn't work with system.js) import { ModalModule } from 'ngx-bootstrap/modal'; // or import { ModalModule } from 'ngx-bootstrap'; @NgModule({ imports: [ModalModule.forRoot(),...] }) export class AppModule(){}
- modal statique Simple
<button type="button" class="btn btn-primary" (click)="staticModal.show()">Static modal</button> <div class="modal fade" bsModal #staticModal="bs-modal" [config]="{backdrop: 'static'}" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true"> <div class="modal-dialog modal-sm"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title pull-left">Static modal</h4> <button type="button" class="close pull-right" aria-label="Close" (click)="staticModal.hide()"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> This is static modal, backdrop click will not close it. Click <b>×</b> to close modal. </div> </div> </div> </div>
Maintenant disponible en tant que paquet npm
@ Stephen Paul Suite ...
- Angular 2 et up Bootstrap css (l'animation est préservée)
- Pas de JQuery
- PAS de bootstrap.js
- prend en charge le contenu modal personnalisé
- prise en charge de plusieurs modals sur le dessus de chacun autre.
- Moduralisé
- Désactiver le défilement quand modal est ouvert
- Modal est détruit lors de la navigation loin.
- initialisation de contenu paresseux, qui obtient
ngOnDestroy
(ed) lorsque le modal est sorti. - Parent de défilement désactivé lorsque le modal est visible
Initialisation de contenu paresseux
Pourquoi?
Dans certains cas, vous pouvez ne pas vouloir modal pour conserver son statut après avoir été fermé, mais plutôt restauré à l'état initial.
Problème modal Original
Passer le contenu directement dans la vue génère réellement initialise avant même que le modal l'obtient. Le modal n'a pas de moyen de tuer un tel contenu même si vous utilisez un wrapper *ngIf
.
Solution
ng-template
. ng-template
ne rend pas jusqu'à ce que ordonné de faire si.
Mon composant.module.ts
...
imports: [
...
ModalModule
]
Mon composant.ts
<button (click)="reuseModal.open()">Open</button>
<app-modal #reuseModal>
<ng-template #header></ng-template>
<ng-template #body>
<app-my-body-component>
<!-- This component will be created only when modal is visible and will be destroyed when it's not. -->
</app-my-body-content>
<ng-template #footer></ng-template>
</app-modal>
Modal.composant.ts
export class ModalComponent ... {
@ContentChild('header') header: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChild('footer') footer: TemplateRef<any>;
...
}
Modal.composant.html
<div ... *ngIf="visible">
...
<div class="modal-body">
ng-container *ngTemplateOutlet="body"></ng-container>
</div>
Références à
Je dois dire que cela n'aurait pas été possible sans l'excellente documentation officielle et communautaire autour du net. Il pourrait aider certains d'entre vous aussi pour mieux comprendre comment ng-template
, *ngTemplateOutlet
et @ContentChild
travail.
Https://angular.io/api/common/NgTemplateOutlet
https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/
https://medium.com/claritydesignsystem/ng-content-the-hidden-docs-96a29d70d11b
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e
Plein copier-coller solution
Modal.composant.html
<div
(click)="onContainerClicked($event)"
class="modal fade"
tabindex="-1"
[ngClass]="{'in': visibleAnimate}"
[ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}"
*ngIf="visible">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<ng-container *ngTemplateOutlet="header"></ng-container>
<button class="close" data-dismiss="modal" type="button" aria-label="Close" (click)="close()">×</button>
</div>
<div class="modal-body">
<ng-container *ngTemplateOutlet="body"></ng-container>
</div>
<div class="modal-footer">
<ng-container *ngTemplateOutlet="footer"></ng-container>
</div>
</div>
</div>
</div>
Modal.composant.ts
/**
* @Stephen Paul https://stackoverflow.com/a/40144809/2013580
* @zurfyx https://stackoverflow.com/a/46949848/2013580
*/
import { Component, OnDestroy, ContentChild, TemplateRef } from '@angular/core';
@Component({
selector: 'app-modal',
templateUrl: 'modal.component.html',
styleUrls: ['modal.component.scss'],
})
export class ModalComponent implements OnDestroy {
@ContentChild('header') header: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChild('footer') footer: TemplateRef<any>;
public visible = false;
public visibleAnimate = false;
ngOnDestroy() {
// Prevent modal from not executing its closing actions if the user navigated away (for example,
// through a link).
this.close();
}
open(): void {
document.body.style.overflow = 'hidden';
this.visible = true;
setTimeout(() => this.visibleAnimate = true, 200);
}
close(): void {
document.body.style.overflow = 'auto';
this.visibleAnimate = false;
setTimeout(() => this.visible = false, 100);
}
onContainerClicked(event: MouseEvent): void {
if ((<HTMLElement>event.target).classList.contains('modal')) {
this.close();
}
}
}
Modal.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ModalComponent } from './modal.component';
@NgModule({
imports: [
CommonModule,
],
exports: [ModalComponent],
declarations: [ModalComponent],
providers: [],
})
export class ModalModule { }
Voici mon implémentation complète du composant modal Bootstrap angular2:
Je suppose que dans votre index principal.fichier html (avec les balises <html>
et <body>
) en bas de la balise <body>
Vous avez:
<script src="assets/js/jquery-2.1.1.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
Modal.composant.ts:
import { Component, Input, Output, ElementRef, EventEmitter, AfterViewInit } from '@angular/core';
declare var $: any;// this is very importnant (to work this line: this.modalEl.modal('show')) - don't do this (becouse this owerride jQuery which was changed by bootstrap, included in main html-body template): let $ = require('../../../../../node_modules/jquery/dist/jquery.min.js');
@Component({
selector: 'modal',
templateUrl: './modal.html',
})
export class Modal implements AfterViewInit {
@Input() title:string;
@Input() showClose:boolean = true;
@Output() onClose: EventEmitter<any> = new EventEmitter();
modalEl = null;
id: string = uniqueId('modal_');
constructor(private _rootNode: ElementRef) {}
open() {
this.modalEl.modal('show');
}
close() {
this.modalEl.modal('hide');
}
closeInternal() { // close modal when click on times button in up-right corner
this.onClose.next(null); // emit event
this.close();
}
ngAfterViewInit() {
this.modalEl = $(this._rootNode.nativeElement).find('div.modal');
}
has(selector) {
return $(this._rootNode.nativeElement).find(selector).length;
}
}
let modal_id: number = 0;
export function uniqueId(prefix: string): string {
return prefix + ++modal_id;
}
Modal.html:
<div class="modal inmodal fade" id="{{modal_id}}" tabindex="-1" role="dialog" aria-hidden="true" #thisModal>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" [ngClass]="{'hide': !(has('mhead') || title) }">
<button *ngIf="showClose" type="button" class="close" (click)="closeInternal()"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<ng-content select="mhead"></ng-content>
<h4 *ngIf='title' class="modal-title">{{ title }}</h4>
</div>
<div class="modal-body">
<ng-content></ng-content>
</div>
<div class="modal-footer" [ngClass]="{'hide': !has('mfoot') }" >
<ng-content select="mfoot"></ng-content>
</div>
</div>
</div>
</div>
Et exemple d'utilisation dans le composant éditeur client: client-modifier-composant.ts:
import { Component } from '@angular/core';
import { ClientService } from './client.service';
import { Modal } from '../common';
@Component({
selector: 'client-edit',
directives: [ Modal ],
templateUrl: './client-edit.html',
providers: [ ClientService ]
})
export class ClientEdit {
_modal = null;
constructor(private _ClientService: ClientService) {}
bindModal(modal) {this._modal=modal;}
open(client) {
this._modal.open();
console.log({client});
}
close() {
this._modal.close();
}
}
Client-modifier.html:
<modal [title]='"Some standard title"' [showClose]='true' (onClose)="close()" #editModal>{{ bindModal(editModal) }}
<mhead>Som non-standart title</mhead>
Some contents
<mfoot><button calss='btn' (click)="close()">Close</button></mfoot>
</modal>
, bien sûr title
, showClose
, <mhead>
et <mfoot>
ar en option paramètres/tags.
J'ai récemment blogué à ce sujet ..
J'ai créé un service réutilisable qu'un composant peut avoir injecté. Une fois injecté, le composant peut communiquer au service s'il est dans un état sale et s'attacher à la navigation du routeur.
Https://long2know.com/2017/01/angular2-menus-navigation-and-dialogs/ https://long2know.com/2017/01/angular2-dialogservice-exploring-bootstrap-part-2/
Vérifiez la boîte de dialogue ASUI qui crée à l'exécution. Il n'y a pas besoin de cacher et montrer la logique. Simplement service va créer un composant à l'exécution en utilisant AOT ASUI MNP
Essayez d'utiliser ng-window, c'est permettre au développeur d'ouvrir et de contrôler complètement plusieurs fenêtres dans des applications à une seule page de manière simple, Pas de Jquery, pas de Bootstrap.
Configration Avilable
- fenêtre Maxmize
- Réduire la fenêtre
- taille Personnalisée,
- posation personnalisée
- la fenêtre est glisser
- bloquer la fenêtre parent ou non
- centrez la fenêtre ou non
- passer les valeurs à la fenêtre chirield
- passer les valeurs de la fenêtre chield à la fenêtre parent
- écoute de la fermeture de la fenêtre chield dans la fenêtre parent
- écoutez l'événement redimensionner avec votre écouteur personnalisé
- Ouvrir avec une taille maximale ou non
- activer et désactiver le redimensionnement de la fenêtre
- Activer et désactiver la maximisation
- Activer et désactiver la minimisation