角度2.0和模态对话框

我试图找到一些例子,关于如何做一个角度2.0确认模态对话框。我一直在使用自举对话框的角度1.0和无法找到任何例子在网络的角度2.0。我还查了角度2.0的医生,没有结果。

有没有办法使用角度2.0引导对话框?

225407 次浏览

这里有一个相当不错的例子,说明如何在 GitHub上的 Angular2应用程序中使用 Bootstrap 模式。

它的要点是您可以将引导 html 和 jquery 初始化封装在一个组件中。我已经创建了一个可重用的 modal组件,它允许您使用模板变量触发一个 open。

<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)可以用作任何其他组件的子视图。它只是一个总是打开或显示的引导模式。它的可见性由 ngIf 语句控制。

错误信息

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">&times;</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>

这是一个父控件示例(为简洁起见,省略了一些不相关的代码) :

父母,父母

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组件:

我假设在 <body>标记底部的主 index.html 文件(带有 <html><body>标记)中有:

  <script src="assets/js/jquery-2.1.1.js"></script>
<script src="assets/js/bootstrap.min.js"></script>

组件:

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

返回文章页面

<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">&times;</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>

以及客户端编辑器组件中的使用示例: Client-edit-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();
}


}

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

当然,titleshowClose<mhead><mfoot>是可选的参数/标签。

  • 角度2向上
  • 引导 CSS (动画保留)
  • 没有 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 用户 ,您需要做一个小小的更改(因为从 Bootstrap 3更新了一个 css 类名)。这句话: [ngClass]="{'in': visibleAnimate}"应改为: [ngClass]="{'show': visibleAnimate}"

为了演示,这里是一个 < a href = “ https://invedd.plnkr.co/7kqyiW97CI696Ixn020g/”rel = “ norefrer”> plunkr

尝试使用 ng- 窗口,它允许开发人员在单页面应用程序中以简单的方式打开和完全控制多个窗口,无 Jquery,无 Bootstrap。

enter image description here

可用配置

  • 最大化窗口
  • 最小化窗口
  • 定制尺寸,
  • 定制职位
  • 窗户是可以拖动的
  • 是否阻止父窗口
  • 不管是不是在窗户中间
  • 将值传递给子窗口
  • 将值从子窗口传递到父窗口
  • 监听关闭父窗口中的子窗口
  • 使用自定义侦听器侦听调整事件的大小
  • 以最大大小打开或不打开
  • 启用和禁用窗口大小调整
  • 启用和禁用最大化
  • 启用和禁用最小化

检查运行时创建的 ASUI 对话框。不需要隐藏和显示逻辑。Simpleservice 将在运行时使用 AOT 创建组件 ASUI NPM

我在我的项目中使用 Ngx-bootstrap

你可以找到演示 给你

Github 是 给你

使用方法:

  1. 安装 Ngx-bootstrap

  2. 导入模块

// 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(){}
  1. 简单静态模态
<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">&times;</span>
</button>
</div>
<div class="modal-body">
This is static modal, backdrop click will not close it.
Click <b>&times;</b> to close modal.
</div>
</div>
</div>
</div>

现在可以买到 NPM 包裹

角定制模式角定制模式


@ Stephen Paul 继续...

  • 角2及以上引导 CSS (动画保留)
  • NO JQuery
  • 没有 bootstrap.js
  • 支持自定义模式内容
  • 在每个模式之上支持多个模式 其他
  • 固定的
  • 当模态打开时禁用滚动
  • 当导航离开时,模态会被破坏。
  • 延迟内容初始化,在模态退出时获取 ngOnDestroy(ed)。
  • 当模式可见时禁用父滚动

延迟内容初始化

为什么?

在某些情况下,您可能不希望在关闭之后通过模态来保留其状态,而是希望恢复到初始状态。

原始模式问题

直接将内容传递到视图中实际上甚至在模态获取内容之前就会对其进行初始化。即使使用 *ngIf包装器,模态也没有杀死这些内容的方法。

解决方案

ng-template直到接到命令才进行渲染。

My 组件模块

...
imports: [
...
ModalModule
]

My 组件

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

Modal.Component. 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 模块

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

角7 + NgBootstrap

一种从主要构件开启模态并将结果返回给主要构件的简便方法。就是我想要的。我创建了一个分步教程,其中包括从头创建一个新项目,安装 ngbootstrap 和创建 Modal。您可以复制它,也可以按照指南操作。

希望这对 Angular 有所帮助!

Https://github.com/wkaczurba/modal-demo

详情:

Mode-simple 模板(mode-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">&times;</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>

Mode-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)-处理返回事件的简单方法:

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

@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;
}
}

干杯