首页 文章

Angular 2.0和模态对话框

提问于
浏览
122

我试图找到一些关于如何在Angular 2.0中进行确认模式对话框的示例 . 我一直在使用Angular 1.0的Bootstrap对话框,无法在Web上找到Angular 2.0的任何示例 . 我也检查了角度2.0文档没有运气 .

有没有办法在Angular 2.0中使用Bootstrap对话框?

谢谢!

9 回答

  • 195

    这是一个很好的例子,说明如何在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包并在app模块中注册模态模块:

    import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
    
    @NgModule({
        imports: [Ng2Bs3ModalModule]
    })
    export class MyAppModule {}
    
  • 2
    • Angular 2及以上

    • Bootstrap css(保留动画)

    • NO JQuery

    • NO bootstrap.js

    • 支持 custom modal content (就像接受的答案一样)

    • 最近添加了对 multiple modals on top of each other 的支持 .

    `

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

    To show the backdrop ,你需要这样的CSS:

    .modal {
      background: rgba(0,0,0,0.6);
    }
    

    The example now allows for multiple modals at the same time . (参见 onContainerClicked() 方法) .

    For Bootstrap 4 css users ,您需要进行1次小改动(因为从Bootstrap 3更新了css类名) . 这一行: [ngClass]="{'in': visibleAnimate}" 应更改为: [ngClass]="{'show': visibleAnimate}"

    为了演示,这里是 plunkr

  • 55

    现在作为NPM包提供

    angular-custom-modal


    @Stephen Paul continuation ......

    • Angular 2及以上Bootstrap css(保留动画)

    • 没有JQuery

    • 没有bootstrap.js

    • 支持自定义模态内容

    • 支持多个模态 .

    • Moduralized

    • Disable scroll when modal is open

    • Modal gets destroyed when navigating away.

    • Lazy content initialization, which gets ngOnDestroy(ed) when the modal is exited.

    • Parent scrolling disabled when modal is visible

    延迟内容初始化

    Why?

    在某些情况下,您可能不希望模态在关闭后保持其状态,而是恢复到初始状态 .

    Original modal issue

    将内容直接传递到视图实际上会在模态获取之前初始化它 . 即使使用 *ngIf 包装器,模式也无法杀死此类内容 .

    Solution

    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>
    

    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>
    

    References

    我不得不说,如果没有关于网络的优秀官方和社区文件,就不可能实现 . 你也可以帮助一些人更好地理解 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.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 { }
    
  • 7

    这是我对modal 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>
    

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

    客户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> 是可选参数/标签 .

  • 7

    检查在运行时创建的ASUI对话框 . 不需要隐藏和显示逻辑 . 简单的服务将在运行时使用AOT ASUI NPM创建一个组件

  • 2

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

    enter image description here

    可用的移民

    • Maxmize窗口

    • 最小化窗口

    • 自定义尺寸,

    • 自定义位置

    • 窗口是可拖动的

    • 阻止父窗口

    • 窗口是否居中

    • 将值传递给chield窗口

    • 将值从chield窗口传递到父窗口

    • 在父窗口中收听关闭的chield窗口

    • 使用自定义侦听器侦听resize事件

    • 以最大尺寸打开或不打开

    • 启用和禁用窗口大小调整

    • 启用和禁用最大化

    • 启用和禁用最小化

  • 0

    这是一种不依赖于jquery或除Angular 2之外的任何其他库的简单方法 . 下面的组件(errorMessage.ts)可以用作任何其他组件的子视图 . 它只是一个始终打开或显示的引导模式 . 它的可见性由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">&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>
    

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

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

    我使用ngx-bootstrap作为我的项目 .

    你可以找到演示here

    github是here

    如何使用:

    //推荐(不适用于system.js)
    从'ngx-bootstrap / modal'导入
    ;
    // 要么
    从'ngx-bootstrap'导入
    ;

    @NgModule({
    导入:[ModalModule.forRoot(),...]
    })
    出口类的AppModule(){}

    • 简单的静态模态

    <button type =“button”class =“btn btn-primary”(click)=“staticModal.show()”>静态模态</ 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”>静态模态</ h4> <button type =“button”class =“close pull-right”aria-label =“Close”(click)=“staticModal.hide()”> <span aria-hidden =“true”>&times; </ span> </按钮> </ DIV> <div class =“modal-body”> 这是静态模态,背景点击不会关闭它 . 单击<b>&times; </ b>关闭模式 . </ DIV> </ DIV> </ DIV> </ DIV>

  • 4

    我最近在博客上写了这个..

    我创建了一个组件可以注入的可重用服务 . 注入后,组件可以与服务进行通信,无论它是否处于脏状态并与路由器导航相关联 .

    https://long2know.com/2017/01/angular2-menus-navigation-and-dialogs/ https://long2know.com/2017/01/angular2-dialogservice-exploring-bootstrap-part-2/

相关问题