Angular 2.0 和模态对话框
Angular 2.0 and Modal Dialog
我试图找到一些关于如何在 Angular 2.0 中执行确认模式对话框的示例。我一直在为 Angular 1.0 使用 Bootstrap 对话框,但无法在网络上找到任何 Angular 2.0 的示例。我还检查了 angular 2.0 文档,但没有运气。
有没有办法在 Angular 2.0 中使用 Bootstrap 对话框?
这是一个非常不错的示例,说明如何在 GitHub 上的 Angular2 应用程序中使用 Bootstrap 模态。
要点是您可以将 bootstrap html 和 jquery 初始化包装在一个组件中。我创建了一个可重用的 modal
组件,允许您使用模板变量触发打开。
<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>
您只需要安装 npm 包并在您的应用模块中注册模态模块:
import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
@NgModule({
imports: [Ng2Bs3ModalModule]
})
export class MyAppModule {}
这是一种简单的方法,不依赖于 jquery 或除 Angular 之外的任何其他库 2。
下面的组件 (errorMessage.ts) 可以用作任何其他组件的子视图。它只是一个始终打开或显示的 bootstrap 模式。它的可见性由 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>
这是一个示例父控件(为简洁起见,省略了一些不相关的代码):
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...
这是我对模态 bootstrap angular2 组件的完整实现:
我假设在您的 index.html 主文件(带有 <html>
和 <body>
标签)的 <body>
标签底部,您有:
<script src="assets/js/jquery-2.1.1.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
modal.component.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>
以及在客户端编辑器组件中的使用示例:
客户端编辑-component.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();
}
}
客户端-edit.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>
当然 title
、showClose
、<mhead>
和 <mfoot>
是可选的 parameters/tags.
- Angular 2 岁及以上
- Bootstrapcss(动画保留)
- 没有JQuery
- 没有bootstrap.js
- 支持自定义模式内容(就像接受的答案一样)
- 最近添加了对多个模态框的支持。
`
@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();
}
}
}
要显示背景,您需要这样的东西CSS:
.modal {
background: rgba(0,0,0,0.6);
}
该示例现在允许同时使用多个模式。 (参见 onContainerClicked()
方法)。
对于 Bootstrap 4 css 用户,您需要进行 1 处小改动(因为 css class 名称更新自 Bootstrap 3)。这一行:
[ngClass]="{'in': visibleAnimate}"
应更改为:
[ngClass]="{'show': visibleAnimate}"
为了演示,这里有一个plunkr
尝试使用ng-window,它允许开发人员以简单的方式在单页应用程序中打开并完全控制多个windows,否Jquery,否Bootstrap。
可用配置
- 最大化window
- 最小化window
- 自定义尺寸,
- 自定义位置
- window 可拖动
- 是否屏蔽parentwindow
- 是否居中window
- 将值传递给孩子 window
- 将值从孩子 window 传递给 parent window
- 收听 window 在 parent window
- 使用自定义侦听器侦听调整大小事件
- 是否以最大尺寸打开
- 启用和禁用window调整大小
- 启用和禁用最大化
- 启用和禁用最小化
检查在运行时创建的 ASUI 对话框。不需要隐藏和显示逻辑。 Simply service 将在运行时使用 AOT 创建一个组件
ASUI NPM
我的项目使用 ngx-bootstrap。
您可以找到演示 here
github是here
使用方法:
导入到您的模块
// 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(){}
- 简单静态模态
<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>
现已作为 NPM package
提供
@Stephen Paul ...
- Angular 2 及以上 Bootstrap css(保留动画)
- 否 JQuery
- 否 bootstrap.js
- 支持自定义模态内容
- 支持每个模态框之上的多个模态框
其他.
- 模块化
- 模式打开时禁用滚动
- Modal 在离开时被销毁。
- 惰性内容初始化,在退出模式时获取
ngOnDestroy
(ed)。
- 当模态可见时禁用父级滚动
惰性内容初始化
为什么?
在某些情况下,您可能不希望模态在关闭后保持其状态,而是恢复到初始状态。
原始模态问题
将内容直接传递到视图中实际上会在模式获取它之前生成初始化它。即使使用 *ngIf
包装器,模态也无法删除此类内容。
解决方案
ng-template
。 ng-template
在收到命令之前不会呈现。
我的-component.module.ts
...
imports: [
...
ModalModule
]
我的-component.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>
模态.component.ts
export class ModalComponent ... {
@ContentChild('header') header: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChild('footer') footer: TemplateRef<any>;
...
}
modal.component.html
<div ... *ngIf="visible">
...
<div class="modal-body">
ng-container *ngTemplateOutlet="body"></ng-container>
</div>
参考文献
我不得不说,如果没有网上优秀的官方和社区文档,这是不可能的。它也可能帮助你们中的一些人更好地理解 ng-template
、*ngTemplateOutlet
和 @ContentChild
的工作原理。
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
完整的复制粘贴解决方案
modal.component.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>
模态.component.ts
/**
* @Stephen Paul
* @zurfyx
*/
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 { }
Angular 7 + NgBootstrap
一种从主组件打开模式并将结果传回给它的简单方法。是我想要的。我创建了一个分步教程,其中包括从头开始创建一个新项目、安装 ngbootstrap 和创建 Modal。您可以克隆它或按照指南进行操作。
希望这对 Angular 的新手有所帮助!
https://github.com/wkaczurba/modal-demo
详情:
modal-简单模板(modal-simple.component.html):
<ng-template #content let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Are you sure?</h4>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>You have not finished reading my code. Are you sure you want to close?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="modal.close('yes')">Yes</button>
<button type="button" class="btn btn-outline-dark" (click)="modal.close('no')">No</button>
</div>
</ng-template>
模态-simple.component.ts:
import { Component, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-modal-simple',
templateUrl: './modal-simple.component.html',
styleUrls: ['./modal-simple.component.css']
})
export class ModalSimpleComponent implements OnInit {
@ViewChild('content') content;
@Output() result : EventEmitter<string> = new EventEmitter();
constructor(private modalService : NgbModal) { }
open() {
this.modalService.open(this.content, {ariaLabelledBy: 'modal-simple-title'})
.result.then((result) => { console.log(result as string); this.result.emit(result) },
(reason) => { console.log(reason as string); this.result.emit(reason) })
}
ngOnInit() {
}
}
它的演示 (app.component.html) - 处理 return 事件的简单方法:
<app-modal-simple #mymodal (result)="onModalClose($event)"></app-modal-simple>
<button (click)="mymodal.open()">Open modal</button>
<p>
Result is {{ modalCloseResult }}
</p>
app.component.ts - onModalClosed 在模态关闭后执行:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
modalCloseResult : string;
title = 'modal-demo';
onModalClose(reason : string) {
this.modalCloseResult = reason;
}
}
干杯
我试图找到一些关于如何在 Angular 2.0 中执行确认模式对话框的示例。我一直在为 Angular 1.0 使用 Bootstrap 对话框,但无法在网络上找到任何 Angular 2.0 的示例。我还检查了 angular 2.0 文档,但没有运气。
有没有办法在 Angular 2.0 中使用 Bootstrap 对话框?
这是一个非常不错的示例,说明如何在 GitHub 上的 Angular2 应用程序中使用 Bootstrap 模态。
要点是您可以将 bootstrap html 和 jquery 初始化包装在一个组件中。我创建了一个可重用的 modal
组件,允许您使用模板变量触发打开。
<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>
您只需要安装 npm 包并在您的应用模块中注册模态模块:
import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
@NgModule({
imports: [Ng2Bs3ModalModule]
})
export class MyAppModule {}
这是一种简单的方法,不依赖于 jquery 或除 Angular 之外的任何其他库 2。 下面的组件 (errorMessage.ts) 可以用作任何其他组件的子视图。它只是一个始终打开或显示的 bootstrap 模式。它的可见性由 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>
这是一个示例父控件(为简洁起见,省略了一些不相关的代码):
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...
这是我对模态 bootstrap angular2 组件的完整实现:
我假设在您的 index.html 主文件(带有 <html>
和 <body>
标签)的 <body>
标签底部,您有:
<script src="assets/js/jquery-2.1.1.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
modal.component.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>
以及在客户端编辑器组件中的使用示例: 客户端编辑-component.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();
}
}
客户端-edit.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>
当然 title
、showClose
、<mhead>
和 <mfoot>
是可选的 parameters/tags.
- Angular 2 岁及以上
- Bootstrapcss(动画保留)
- 没有JQuery
- 没有bootstrap.js
- 支持自定义模式内容(就像接受的答案一样)
- 最近添加了对多个模态框的支持。
`
@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();
}
}
}
要显示背景,您需要这样的东西CSS:
.modal {
background: rgba(0,0,0,0.6);
}
该示例现在允许同时使用多个模式。 (参见 onContainerClicked()
方法)。
对于 Bootstrap 4 css 用户,您需要进行 1 处小改动(因为 css class 名称更新自 Bootstrap 3)。这一行:
[ngClass]="{'in': visibleAnimate}"
应更改为:
[ngClass]="{'show': visibleAnimate}"
为了演示,这里有一个plunkr
尝试使用ng-window,它允许开发人员以简单的方式在单页应用程序中打开并完全控制多个windows,否Jquery,否Bootstrap。
可用配置
- 最大化window
- 最小化window
- 自定义尺寸,
- 自定义位置
- window 可拖动
- 是否屏蔽parentwindow
- 是否居中window
- 将值传递给孩子 window
- 将值从孩子 window 传递给 parent window
- 收听 window 在 parent window
- 使用自定义侦听器侦听调整大小事件
- 是否以最大尺寸打开
- 启用和禁用window调整大小
- 启用和禁用最大化
- 启用和禁用最小化
检查在运行时创建的 ASUI 对话框。不需要隐藏和显示逻辑。 Simply service 将在运行时使用 AOT 创建一个组件 ASUI NPM
我的项目使用 ngx-bootstrap。
您可以找到演示 here
github是here
使用方法:
导入到您的模块
// 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(){}
- 简单静态模态
<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>
现已作为 NPM package
提供@Stephen Paul
- Angular 2 及以上 Bootstrap css(保留动画)
- 否 JQuery
- 否 bootstrap.js
- 支持自定义模态内容
- 支持每个模态框之上的多个模态框 其他.
- 模块化
- 模式打开时禁用滚动
- Modal 在离开时被销毁。
- 惰性内容初始化,在退出模式时获取
ngOnDestroy
(ed)。 - 当模态可见时禁用父级滚动
惰性内容初始化
为什么?
在某些情况下,您可能不希望模态在关闭后保持其状态,而是恢复到初始状态。
原始模态问题
将内容直接传递到视图中实际上会在模式获取它之前生成初始化它。即使使用 *ngIf
包装器,模态也无法删除此类内容。
解决方案
ng-template
。 ng-template
在收到命令之前不会呈现。
我的-component.module.ts
...
imports: [
...
ModalModule
]
我的-component.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>
模态.component.ts
export class ModalComponent ... {
@ContentChild('header') header: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChild('footer') footer: TemplateRef<any>;
...
}
modal.component.html
<div ... *ngIf="visible">
...
<div class="modal-body">
ng-container *ngTemplateOutlet="body"></ng-container>
</div>
参考文献
我不得不说,如果没有网上优秀的官方和社区文档,这是不可能的。它也可能帮助你们中的一些人更好地理解 ng-template
、*ngTemplateOutlet
和 @ContentChild
的工作原理。
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
完整的复制粘贴解决方案
modal.component.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>
模态.component.ts
/**
* @Stephen Paul
* @zurfyx
*/
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 { }
Angular 7 + NgBootstrap
一种从主组件打开模式并将结果传回给它的简单方法。是我想要的。我创建了一个分步教程,其中包括从头开始创建一个新项目、安装 ngbootstrap 和创建 Modal。您可以克隆它或按照指南进行操作。
希望这对 Angular 的新手有所帮助!
https://github.com/wkaczurba/modal-demo
详情:
modal-简单模板(modal-simple.component.html):
<ng-template #content let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Are you sure?</h4>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>You have not finished reading my code. Are you sure you want to close?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="modal.close('yes')">Yes</button>
<button type="button" class="btn btn-outline-dark" (click)="modal.close('no')">No</button>
</div>
</ng-template>
模态-simple.component.ts:
import { Component, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-modal-simple',
templateUrl: './modal-simple.component.html',
styleUrls: ['./modal-simple.component.css']
})
export class ModalSimpleComponent implements OnInit {
@ViewChild('content') content;
@Output() result : EventEmitter<string> = new EventEmitter();
constructor(private modalService : NgbModal) { }
open() {
this.modalService.open(this.content, {ariaLabelledBy: 'modal-simple-title'})
.result.then((result) => { console.log(result as string); this.result.emit(result) },
(reason) => { console.log(reason as string); this.result.emit(reason) })
}
ngOnInit() {
}
}
它的演示 (app.component.html) - 处理 return 事件的简单方法:
<app-modal-simple #mymodal (result)="onModalClose($event)"></app-modal-simple>
<button (click)="mymodal.open()">Open modal</button>
<p>
Result is {{ modalCloseResult }}
</p>
app.component.ts - onModalClosed 在模态关闭后执行:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
modalCloseResult : string;
title = 'modal-demo';
onModalClose(reason : string) {
this.modalCloseResult = reason;
}
}
干杯