Hộp thoại Angular 2.0 và Modal


128

Tôi đang cố gắng tìm một số ví dụ về cách thực hiện hộp thoại xác nhận phương thức trong Angular 2.0. Tôi đã sử dụng hộp thoại Bootstrap cho Angular 1.0 và không thể tìm thấy bất kỳ ví dụ nào trên web cho Angular 2.0. Tôi cũng đã kiểm tra các tài liệu 2.0 góc cạnh không có may mắn.

Có cách nào để sử dụng hộp thoại Bootstrap với Angular 2.0 không?


Tôi đã tìm thấy ví dụ này. Có lẽ nó sẽ giúp bạn angensescript.com/angular2-modal-window-with-bootstrap-style
Puya Sarmidani

1
Tôi đang sử dụng cái này với RC3 và nội dung khá hay với nó: valor-software.com/ng2-bootstrap/#/modals
mentat

Nhờ @Sam, tôi đã có một khởi đầu tốt. Tuy nhiên, tôi nhận thấy rằng thành phần gọi điện không biết nút nào được nhấp. Sau một số nghiên cứu, tôi đã có thể sử dụng Đài quan sát thay vì EventEmitters để đưa ra một giải pháp thanh lịch hơn .
Jon


@mentat, url được cập nhật valor-software.com/ngx-bootstrap/#/modals
Anand Rockzz

Câu trả lời:


199
  • Góc 2 trở lên
  • Bootstrap css (hoạt hình được bảo tồn)
  • KHÔNG JQuery
  • KHÔNG bootstrap.js
  • Hỗ trợ nội dung phương thức tùy chỉnh (giống như câu trả lời được chấp nhận)
  • Gần đây đã thêm hỗ trợ cho nhiều phương thức chồng lên nhau .

`

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

Để hiển thị phông nền , bạn sẽ cần một cái gì đó như CSS này:

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

Ví dụ bây giờ cho phép nhiều phương thức cùng một lúc . (xem onContainerClicked()phương pháp).

Đối với người dùng Bootstrap 4 css , bạn cần thực hiện 1 thay đổi nhỏ (vì tên lớp css đã được cập nhật từ Bootstrap 3). Dòng này: [ngClass]="{'in': visibleAnimate}"nên được đổi thành: [ngClass]="{'show': visibleAnimate}"

Để chứng minh, đây là một plunkr


Có một gotcha mặc dù. Vì các nút được bọc bên trong một phần tử phụ ở đây, nên kiểu bootstrap sẽ không áp dụng lề cho các nút (ít nhất là trong v4). loại bỏ gói div.modal-footervà thay đổi .app-modal-footerđể .modal-footersửa lỗi này.
Axel Köhler

55

Đây là một ví dụ khá hay về cách bạn có thể sử dụng phương thức Bootstrap trong ứng dụng Angular2 trên GitHub .

Ý chính của nó là bạn có thể gói khởi động html và jquery bootstrap trong một thành phần. Tôi đã tạo một modalthành phần có thể sử dụng lại cho phép bạn kích hoạt mở bằng biến mẫu.

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

Bạn chỉ cần cài đặt gói npm và đăng ký mô-đun phương thức trong mô-đun ứng dụng của bạn:

import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';

@NgModule({
    imports: [Ng2Bs3ModalModule]
})
export class MyAppModule {}

8
Bummer - dựa vào jquery như một sự phụ thuộc :(
brando

52
Vâng vâng, bootstrap dựa vào nó và tôi không làm việc trong việc viết lại các thư viện.
Douglas Ludlow

2
Điều này có thể được thực hiện mà không cần jQuery. Tôi đã sử dụng câu trả lời của Sam cùng với hướng dẫn tại koscielniak.me/post/2016/03/angular2-confirm-dialog-component để viết một dịch vụ và thành phần phương thức liên quan.
BeetleJuice

Nếu bạn không sử dụng bootstrap trong dự án của mình, đừng quên thêm liên kết vào bootstrap.css. Trang github quên đề cập đến điều này.
Shekhar

46

Đây là một cách tiếp cận đơn giản không phụ thuộc vào jquery hoặc bất kỳ thư viện nào khác ngoại trừ Angular 2. Thành phần bên dưới (errorMessage.ts) có thể được sử dụng làm chế độ xem con của bất kỳ thành phần nào khác. Nó chỉ đơn giản là một phương thức bootstrap luôn mở hoặc hiển thị. Tầm nhìn của nó bị chi phối bởi câu lệnh ng If.

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>

Đây là một ví dụ kiểm soát cha mẹ (một số mã không liên quan đã bị bỏ qua cho ngắn gọn):

cha mẹ

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']);
            }
        });
    }

}

cha mẹ.html

<app-error-message></app-error-message>
// your html...

3
tốt đẹp - có thể giải thíchclass="modal fade show in danger"
bensiu

@bensiu Tôi đoán rằng bộ chọn lớp không được sử dụng - trừ khi họ có bộ chọn kiểu css cho tất cả các từ đó, ví dụ: 'in'
Drenai

Làm thế nào để bạn có được hiệu ứng mờ dần trong / ra với điều này?
Big McLUNDHuge

10

Hiện có sẵn dưới dạng gói NPM

góc-tùy chỉnh-phương thức


@Stephen Paul tiếp tục ...

  • Angular 2 trở lên Bootstrap css (hoạt hình được bảo tồn)
  • KHÔNG JQuery
  • KHÔNG bootstrap.js
  • Hỗ trợ nội dung phương thức tùy chỉnh
  • Hỗ trợ cho nhiều phương thức trên đầu nhau.
  • Điều chế
  • Vô hiệu hóa cuộn khi chế độ được mở
  • Modal bị phá hủy khi điều hướng đi.
  • Khởi tạo nội dung lười biếng, được ngOnDestroy(ed) khi phương thức được thoát.
  • Cuộn cha mẹ bị vô hiệu hóa khi chế độ hiển thị

Khởi tạo nội dung lười biếng

Tại sao?

Trong một số trường hợp, bạn có thể không muốn phương thức giữ lại trạng thái của nó sau khi đã bị đóng, nhưng được khôi phục về trạng thái ban đầu.

Vấn đề phương thức gốc

Truyền nội dung đơn giản vào chế độ xem thực sự tạo ra khởi tạo nó ngay cả trước khi phương thức có được nó. Phương thức không có cách nào để giết nội dung đó ngay cả khi sử dụng *ngIftrình bao bọc.

Giải pháp

ng-template. ng-templatekhông kết xuất cho đến khi được yêu cầu làm như vậy.

my-thành phần.module.ts

...
imports: [
  ...
  ModalModule
]

thành phần của tôi

<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ười giới thiệu

Tôi phải nói rằng điều đó sẽ không thể xảy ra nếu không có tài liệu chính thức và cộng đồng tuyệt vời trên mạng. Nó có thể giúp một số bạn quá để hiểu làm thế nào tốt hơn ng-template, *ngTemplateOutlet@ContentChildcông việc.

https://angular.io/api/common/NgTemplateOutlet
https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/
https://medium.com/claritydesignsystem/ng-content -the-ẩn-docs-96a29d70d11b
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in -angular-896b0c689f6e

Giải pháp sao chép toàn bộ

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

Tôi sử dụng ngx-bootstrap cho dự án của tôi.

Bạn có thể tìm thấy bản demo ở đây

Các github là ở đây

Cách sử dụng:

  1. Cài đặt ngx-bootstrap

  2. Nhập vào mô-đun của bạn

// 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. Phương thức tĩnh đơn giản
<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>

4

Dưới đây là toàn bộ triển khai của tôi về thành phần bootstrap angular2:

Tôi giả sử rằng trong tệp index.html chính của bạn (có <html><body>thẻ) ở cuối <body>thẻ bạn có:

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

Và ví dụ về việc sử dụng trong client Editor thành phần: 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>

Ofcourse title, showClose, <mhead><mfoot>ar tùy chọn thông số / thẻ.


2
Thay vì bindModal(modal) {this._modal=modal;}, bạn có thể sử dụng ViewChildchú thích của góc , như vậy : @ViewChild('editModal') _modal: Modal;. Nó xử lý các ràng buộc cho bạn đằng sau hậu trường.
Douglas Ludlow


0

hãy thử sử dụng ng-window, nó cho phép nhà phát triển mở và kiểm soát hoàn toàn nhiều cửa sổ trong các ứng dụng trang đơn theo cách đơn giản, Không Jquery, Không Bootstrap.

nhập mô tả hình ảnh ở đây

Cấu hình sẵn có

  • Tối đa hóa cửa sổ
  • Thu nhỏ cửa sổ
  • Kích thước tùy chỉnh,
  • Tùy chỉnh vị trí
  • cửa sổ có thể kéo
  • Chặn cửa sổ cha mẹ hay không
  • Căn giữa cửa sổ hay không
  • Truyền giá trị cho cửa sổ chield
  • Truyền giá trị từ cửa sổ chield sang cửa sổ cha
  • Nghe đóng cửa sổ chield trong cửa sổ cha
  • Nghe để thay đổi kích thước sự kiện với người nghe tùy chỉnh của bạn
  • Mở với kích thước tối đa hay không
  • Kích hoạt và vô hiệu hóa thay đổi kích thước cửa sổ
  • Kích hoạt và vô hiệu hóa tối đa hóa
  • Kích hoạt và vô hiệu hóa tối thiểu hóa

-1 Điều này hữu ích như thế nào? Nó không giải quyết bất kỳ yêu cầu nào theo quy định của OP. Đây là bài viết thứ 4 tôi thấy bạn đang troll câu trả lời của bạn!
AVN

0

Góc 7 + NgBootstrap

Một cách đơn giản để mở phương thức từ thành phần chính và chuyển kết quả trở lại cho nó. là những gì tôi muốn. Tôi đã tạo một hướng dẫn từng bước bao gồm tạo một dự án mới từ đầu, cài đặt ngbootstrap và tạo Modal. Bạn có thể nhân bản nó hoặc làm theo hướng dẫn.

Hy vọng điều này sẽ giúp mới cho Angular.!

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

Chi tiết:

mẫu đơn giản 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">&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>

Phương thức-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() {
  }

}

Bản demo của nó (app.component.html) - cách đơn giản để xử lý sự kiện trả lại:

<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 - onModalCloses được thực thi khi đóng chế độ:

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

Chúc mừng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.